From 8b068c2993b2483e32ee66eb7498ae16f0692906 Mon Sep 17 00:00:00 2001 From: "Thierry FOURNIER / OZON.IO" Date: Mon, 10 Oct 2016 11:59:50 +0200 Subject: [PATCH] MINOR: ssl: add debug traces Add some debug trace when haproxy is configured in debug & verbose mode. This is useful for openssl tests. Typically, the error "SSL handshake failure" can be caused by a lot of protocol error. This patch details the encountered error. For exemple: OpenSSL error 0x1408a0c1: ssl3_get_client_hello: no shared cipher Note that my compilator (gcc-4.7) refuse to considers the function ssl_sock_dump_errors() as inline. The condition "if" ensure that the content of the function is not executed in normal case. It should be a pity to call a function just for testing its execution condition, so I use the macro "forceinline". --- src/ssl_sock.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index e5a6f0a56..f00b358b8 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -199,6 +199,27 @@ struct ocsp_cbk_arg { }; }; +/* + * This function gives the detail of the SSL error. It is used only + * if the debug mode and the verbose mode are activated. It dump all + * the SSL error until the stack was empty. + */ +static forceinline void ssl_sock_dump_errors(struct connection *conn) +{ + unsigned long ret; + + if (unlikely(global.mode & MODE_DEBUG)) { + while(1) { + ret = ERR_get_error(); + if (ret == 0) + return; + fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n", + (unsigned short)conn->t.sock.fd, ret, + ERR_func_error_string(ret), ERR_reason_error_string(ret)); + } + } +} + /* * This function returns the number of seconds elapsed * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the @@ -1014,6 +1035,7 @@ int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store) } if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) { + ssl_sock_dump_errors(conn); ERR_clear_error(); return 1; } @@ -1027,6 +1049,7 @@ int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store) /* check if certificate error needs to be ignored */ if (objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) { + ssl_sock_dump_errors(conn); ERR_clear_error(); return 1; } @@ -3542,6 +3565,7 @@ reneg_ok: out_error: /* Clear openssl global errors stack */ + ssl_sock_dump_errors(conn); ERR_clear_error(); /* free resumed session if exists */ @@ -3619,6 +3643,7 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun conn->flags |= CO_FL_ERROR; /* Clear openssl global errors stack */ + ssl_sock_dump_errors(conn); ERR_clear_error(); } goto read0; @@ -3653,6 +3678,7 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun return done; out_error: /* Clear openssl global errors stack */ + ssl_sock_dump_errors(conn); ERR_clear_error(); conn->flags |= CO_FL_ERROR; @@ -3749,6 +3775,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl out_error: /* Clear openssl global errors stack */ + ssl_sock_dump_errors(conn); ERR_clear_error(); conn->flags |= CO_FL_ERROR; @@ -3774,6 +3801,7 @@ static void ssl_sock_shutw(struct connection *conn, int clean) /* no handshake was in progress, try a clean ssl shutdown */ if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) { /* Clear openssl global errors stack */ + ssl_sock_dump_errors(conn); ERR_clear_error(); } @@ -6021,6 +6049,9 @@ static void __ssl_sock_init(void) #ifndef OPENSSL_NO_DH ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); #endif + + /* Load SSL string for the verbose & debug mode. */ + ERR_load_SSL_strings(); } __attribute__((destructor))