#include <haproxy/proxy-t.h>
#include <haproxy/quic_conn-t.h>
#include <haproxy/ssl_sock-t.h>
+#include <haproxy/stats.h>
#include <haproxy/thread.h>
extern struct list tlskeys_reference;
void ssl_sock_update_counters(SSL *ssl,
struct ssl_counters *counters,
struct ssl_counters *counters_px, int backend);
+void ssl_sock_handle_hs_error(struct connection *conn);
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
struct buffer *tlskey);
return ret;
}
+/* Set at <counters> and <counters_px> addresses the SSL statistical counters */
+static inline void ssl_sock_get_stats_counters(struct connection *conn,
+ struct ssl_counters **counters,
+ struct ssl_counters **counters_px)
+{
+ switch (obj_type(conn->target)) {
+ case OBJ_TYPE_LISTENER: {
+ struct listener *li = __objt_listener(conn->target);
+ *counters = EXTRA_COUNTERS_GET(li->extra_counters, &ssl_stats_module);
+ *counters_px = EXTRA_COUNTERS_GET(li->bind_conf->frontend->extra_counters_fe,
+ &ssl_stats_module);
+ break;
+ }
+ case OBJ_TYPE_SERVER: {
+ struct server *srv = __objt_server(conn->target);
+ *counters = EXTRA_COUNTERS_GET(srv->extra_counters, &ssl_stats_module);
+ *counters_px = EXTRA_COUNTERS_GET(srv->proxy->extra_counters_be,
+ &ssl_stats_module);
+ break;
+ }
+ default:
+ break;
+ }
+}
#endif /* USE_OPENSSL */
#endif /* _HAPROXY_SSL_SOCK_H */
}
}
+/* Handle the handshake error for <conn> connection.
+ * Also used by QUIC.
+ */
+void ssl_sock_handle_hs_error(struct connection *conn)
+{
+ struct ssl_counters *counters = NULL;
+ struct ssl_counters *counters_px = NULL;
+
+ /* get counters */
+ ssl_sock_get_stats_counters(conn, &counters, &counters_px);
+
+ /* free resumed session if exists */
+ if (objt_server(conn->target)) {
+ struct server *s = __objt_server(conn->target);
+ /* RWLOCK: only rdlock the SSL cache even when writing in it because there is
+ * one cache per thread, it only prevents to flush it from the CLI in
+ * another thread */
+
+ HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock);
+ if (s->ssl_ctx.reused_sess[tid].ptr)
+ ha_free(&s->ssl_ctx.reused_sess[tid].ptr);
+ HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock);
+ }
+
+ if (counters) {
+ HA_ATOMIC_INC(&counters->failed_handshake);
+ HA_ATOMIC_INC(&counters_px->failed_handshake);
+ }
+
+ /* Report an HS error only on SSL error */
+ if (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH)))
+ conn_report_term_evt(conn, tevt_loc_hs, hs_tevt_type_truncated_rcv_err);
+
+ /* Fail on all other handshake errors */
+ conn->flags |= CO_FL_ERROR;
+ if (!conn->err_code)
+ conn->err_code = CO_ER_SSL_HANDSHAKE;
+}
+
/* This is the callback which is used when an SSL handshake is pending. It
* updates the FD status if it wants some polling before being called again.
* It returns 0 if it fails in a fatal way or needs to poll to go further,
int ret;
struct ssl_counters *counters = NULL;
struct ssl_counters *counters_px = NULL;
- struct listener *li;
- struct server *srv = NULL;
socklen_t lskerr;
int skerr;
if (!conn_ctrl_ready(conn))
return 0;
- /* get counters */
- switch (obj_type(conn->target)) {
- case OBJ_TYPE_LISTENER:
- li = __objt_listener(conn->target);
- counters = EXTRA_COUNTERS_GET(li->extra_counters, &ssl_stats_module);
- counters_px = EXTRA_COUNTERS_GET(li->bind_conf->frontend->extra_counters_fe,
- &ssl_stats_module);
- break;
-
- case OBJ_TYPE_SERVER:
- srv = __objt_server(conn->target);
- counters = EXTRA_COUNTERS_GET(srv->extra_counters, &ssl_stats_module);
- counters_px = EXTRA_COUNTERS_GET(srv->proxy->extra_counters_be,
- &ssl_stats_module);
- break;
-
- default:
- break;
- }
-
if (!ctx)
goto out_error;
if (global_ssl.async)
SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
#endif
+ ssl_sock_get_stats_counters(conn, &counters, &counters_px);
/* Handshake succeeded */
- ssl_sock_update_counters(ctx->ssl, counters, counters_px, !!srv);
+ ssl_sock_update_counters(ctx->ssl, counters, counters_px,
+ !!objt_server(conn->target));
TRACE_LEAVE(SSL_EV_CONN_HNDSHK, conn, ctx->ssl);
/* Clear openssl global errors stack */
ssl_sock_dump_errors(conn, NULL);
ERR_clear_error();
-
- /* free resumed session if exists */
- if (objt_server(conn->target)) {
- struct server *s = __objt_server(conn->target);
- /* RWLOCK: only rdlock the SSL cache even when writing in it because there is
- * one cache per thread, it only prevents to flush it from the CLI in
- * another thread */
-
- HA_RWLOCK_RDLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock);
- if (s->ssl_ctx.reused_sess[tid].ptr)
- ha_free(&s->ssl_ctx.reused_sess[tid].ptr);
- HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock);
- }
-
- if (counters) {
- HA_ATOMIC_INC(&counters->failed_handshake);
- HA_ATOMIC_INC(&counters_px->failed_handshake);
- }
-
- /* Report an HS error only on SSL error */
- if (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH)))
- conn_report_term_evt(conn, tevt_loc_hs, hs_tevt_type_truncated_rcv_err);
-
- /* Fail on all other handshake errors */
- conn->flags |= CO_FL_ERROR;
- if (!conn->err_code)
- conn->err_code = CO_ER_SSL_HANDSHAKE;
+ ssl_sock_handle_hs_error(conn);
TRACE_ERROR("handshake error", SSL_EV_CONN_HNDSHK|SSL_EV_CONN_ERR, conn, (ctx ? ctx->ssl : NULL), &conn->err_code, (ctx ? &ctx->error_code : NULL));
return 0;