From: Amaury Denoyelle Date: Wed, 19 Jan 2022 09:03:30 +0000 (+0100) Subject: MEDIUM: quic/ssl: add new ex data for quic_conn X-Git-Tag: v2.6-dev1~93 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9320dd53850aeb73f6637d2bc96503dea0fd67f5;p=thirdparty%2Fhaproxy.git MEDIUM: quic/ssl: add new ex data for quic_conn Allow to register quic_conn as ex-data in SSL callbacks. A new index is used to identify it as ssl_qc_app_data_index. Replace connection by quic_conn as SSL ex-data when initializing the QUIC SSL session. When using SSL callbacks in QUIC context, the connection is now NULL. Used quic_conn instead to retrieve the required parameters. Also clean up The same changes are conducted inside the QUIC SSL methods of xprt-quic : connection instance usage is replaced by quic_conn. --- diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h index fd45c4beb3..657d8967ac 100644 --- a/include/haproxy/ssl_sock.h +++ b/include/haproxy/ssl_sock.h @@ -42,6 +42,9 @@ extern struct methodVersions methodVersions[]; __decl_thread(extern HA_SPINLOCK_T ckch_lock); extern struct pool_head *pool_head_ssl_capture; extern int ssl_app_data_index; +#ifdef USE_QUIC +extern int ssl_qc_app_data_index; +#endif /* USE_QUIC */ extern unsigned int openssl_engines_initialized; extern int nb_engines; extern struct xprt_ops ssl_sock; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 576b21d382..1aa46d74f7 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -436,6 +436,9 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path) struct pool_head *pool_head_ssl_capture __read_mostly = NULL; int ssl_capture_ptr_index = -1; int ssl_app_data_index = -1; +#ifdef USE_QUIC +int ssl_qc_app_data_index = -1; +#endif /* USE_QUIC */ #ifdef HAVE_SSL_KEYLOG int ssl_keylog_index = -1; @@ -1520,17 +1523,29 @@ out: void ssl_sock_infocbk(const SSL *ssl, int where, int ret) { struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); - struct ssl_sock_ctx *ctx = conn->xprt_ctx; +#ifdef USE_QUIC + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); +#endif /* USE_QUIC */ + struct ssl_sock_ctx *ctx = NULL; + BIO *write_bio; (void)ret; /* shut gcc stupid warning */ + if (conn) + ctx = conn->xprt_ctx; +#ifdef USE_QUIC + else if (qc) + ctx = qc->xprt_ctx; +#endif /* USE_QUIC */ + BUG_ON(!ctx); + #ifndef SSL_OP_NO_RENEGOTIATION /* Please note that BoringSSL defines this macro to zero so don't * change this to #if and do not assign a default value to this macro! */ if (where & SSL_CB_HANDSHAKE_START) { /* Disable renegotiation (CVE-2009-3555) */ - if ((conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) { + if (conn && (conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) { conn->flags |= CO_FL_ERROR; conn->err_code = CO_ER_SSL_RENEG; } @@ -1980,21 +1995,21 @@ static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out, { struct ssl_bind_conf *conf = arg; #ifdef USE_QUIC - struct connection *conn = SSL_get_ex_data(s, ssl_app_data_index); + struct quic_conn *qc = SSL_get_ex_data(s, ssl_qc_app_data_index); #endif if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str, conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) { #ifdef USE_QUIC - if (conn->qc) - quic_set_tls_alert(conn->qc, SSL_AD_NO_APPLICATION_PROTOCOL); + if (qc) + quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL); #endif return SSL_TLSEXT_ERR_NOACK; } #ifdef USE_QUIC - if (conn->qc && !quic_set_app_ops(conn->qc, *out, *outlen)) { - quic_set_tls_alert(conn->qc, SSL_AD_NO_APPLICATION_PROTOCOL); + if (qc && !quic_set_app_ops(qc, *out, *outlen)) { + quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL); return SSL_TLSEXT_ERR_NOACK; } #endif @@ -2451,8 +2466,11 @@ int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx) int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) { #endif - struct connection *conn; - struct bind_conf *s; + struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); +#ifdef USE_QUIC + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); +#endif /* USE_QUIC */ + struct bind_conf *s = NULL; const uint8_t *extension_data; size_t extension_len; int has_rsa_sig = 0, has_ecdsa_sig = 0; @@ -2464,17 +2482,22 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) int allow_early = 0; int i; - conn = SSL_get_ex_data(ssl, ssl_app_data_index); - s = __objt_listener(conn->target)->bind_conf; + if (conn) + s = __objt_listener(conn->target)->bind_conf; +#ifdef USE_QUIC + else if (qc) + s = qc->li->bind_conf; +#endif /* USE_QUIC */ + BUG_ON(!s); #ifdef USE_QUIC - if (conn->qc) { + if (qc) { /* Look for the QUIC transport parameters. */ #ifdef OPENSSL_IS_BORINGSSL - if (!SSL_early_callback_ctx_extension_get(ctx, con->qc->tps_tls_ext, + if (!SSL_early_callback_ctx_extension_get(ctx, qc->tps_tls_ext, &extension_data, &extension_len)) #else - if (!SSL_client_hello_get0_ext(ssl, conn->qc->tps_tls_ext, + if (!SSL_client_hello_get0_ext(ssl, qc->tps_tls_ext, &extension_data, &extension_len)) #endif { @@ -2483,17 +2506,17 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) * which would be set after calling quic_set_tls_alert(). */ *al = SSL_AD_MISSING_EXTENSION; - quic_set_tls_alert(conn->qc, SSL_AD_MISSING_EXTENSION); + quic_set_tls_alert(qc, SSL_AD_MISSING_EXTENSION); return 0; } - if (!quic_transport_params_store(conn->qc, 0, extension_data, + if (!quic_transport_params_store(qc, 0, extension_data, extension_data + extension_len)) goto abort; - quic_mux_transport_params_update(conn->qc->qcc); + quic_mux_transport_params_update(qc->qcc); } -#endif +#endif /* USE_QUIC */ if (s->ssl_conf.early_data) allow_early = 1; @@ -2729,7 +2752,8 @@ int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg) abort: /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */ - conn->err_code = CO_ER_SSL_HANDSHAKE; + if (conn) + conn->err_code = CO_ER_SSL_HANDSHAKE; #ifdef OPENSSL_IS_BORINGSSL return ssl_select_cert_error; #else @@ -7653,6 +7677,9 @@ static void __ssl_sock_init(void) ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func); +#ifdef USE_QUIC + ssl_qc_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); +#endif /* USE_QUIC */ #ifdef HAVE_SSL_KEYLOG ssl_keylog_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_keylog_free_func); #endif diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 8e3b1dc21e..71d3b47ef0 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -745,21 +745,20 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level, const uint8_t *read_secret, const uint8_t *write_secret, size_t secret_len) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); - struct quic_tls_ctx *tls_ctx = - &conn->qc->els[ssl_to_quic_enc_level(level)].tls_ctx; + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); + struct quic_tls_ctx *tls_ctx = &qc->els[ssl_to_quic_enc_level(level)].tls_ctx; const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); struct quic_tls_secrets *rx, *tx; - TRACE_ENTER(QUIC_EV_CONN_RWSEC, conn->qc); + TRACE_ENTER(QUIC_EV_CONN_RWSEC, qc); BUG_ON(secret_len > QUIC_TLS_SECRET_LEN); - if (HA_ATOMIC_LOAD(&conn->qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { - TRACE_PROTO("CC required", QUIC_EV_CONN_RWSEC, conn->qc); + if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { + TRACE_PROTO("CC required", QUIC_EV_CONN_RWSEC, qc); goto out; } if (!quic_tls_ctx_keys_alloc(tls_ctx)) { - TRACE_DEVEL("keys allocation failed", QUIC_EV_CONN_RWSEC, conn->qc); + TRACE_DEVEL("keys allocation failed", QUIC_EV_CONN_RWSEC, qc); goto err; } @@ -773,7 +772,7 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level, if (!quic_tls_derive_keys(rx->aead, rx->hp, rx->md, rx->key, rx->keylen, rx->iv, rx->ivlen, rx->hp_key, sizeof rx->hp_key, read_secret, secret_len)) { - TRACE_DEVEL("RX key derivation failed", QUIC_EV_CONN_RWSEC, conn->qc); + TRACE_DEVEL("RX key derivation failed", QUIC_EV_CONN_RWSEC, qc); goto err; } @@ -785,13 +784,13 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level, if (!quic_tls_derive_keys(tx->aead, tx->hp, tx->md, tx->key, tx->keylen, tx->iv, tx->ivlen, tx->hp_key, sizeof tx->hp_key, write_secret, secret_len)) { - TRACE_DEVEL("TX key derivation failed", QUIC_EV_CONN_RWSEC, conn->qc); + TRACE_DEVEL("TX key derivation failed", QUIC_EV_CONN_RWSEC, qc); goto err; } tx->flags |= QUIC_FL_TLS_SECRETS_SET; tp: - if (objt_server(conn->target) && level == ssl_encryption_application) { + if (!qc_is_listener(qc) && level == ssl_encryption_application) { const unsigned char *buf; size_t buflen; @@ -799,19 +798,18 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level, if (!buflen) goto err; - if (!quic_transport_params_store(conn->qc, 1, buf, buf + buflen)) + if (!quic_transport_params_store(qc, 1, buf, buf + buflen)) goto err; } if (level == ssl_encryption_application) { - struct quic_conn *qc = conn->qc; struct quic_tls_kp *prv_rx = &qc->ku.prv_rx; struct quic_tls_kp *nxt_rx = &qc->ku.nxt_rx; struct quic_tls_kp *nxt_tx = &qc->ku.nxt_tx; if (!(rx->secret = pool_alloc(pool_head_quic_tls_secret)) || !(tx->secret = pool_alloc(pool_head_quic_tls_secret))) { - TRACE_DEVEL("Could not allocate secrete keys", QUIC_EV_CONN_RWSEC, conn->qc); + TRACE_DEVEL("Could not allocate secrete keys", QUIC_EV_CONN_RWSEC, qc); goto err; } @@ -826,11 +824,11 @@ int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level, goto err; } out: - TRACE_LEAVE(QUIC_EV_CONN_RWSEC, conn->qc, &level); + TRACE_LEAVE(QUIC_EV_CONN_RWSEC, qc, &level); return 1; err: - TRACE_DEVEL("leaving in error", QUIC_EV_CONN_RWSEC, conn->qc); + TRACE_DEVEL("leaving in error", QUIC_EV_CONN_RWSEC, qc); return 0; } #else @@ -842,13 +840,13 @@ int ha_set_rsec(SSL *ssl, enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); struct quic_tls_ctx *tls_ctx = - &conn->qc->els[ssl_to_quic_enc_level(level)].tls_ctx; + &qc->els[ssl_to_quic_enc_level(level)].tls_ctx; - TRACE_ENTER(QUIC_EV_CONN_RSEC, conn->qc); - if (HA_ATOMIC_LOAD(&conn->qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { - TRACE_PROTO("CC required", QUIC_EV_CONN_RSEC, conn->qc); + TRACE_ENTER(QUIC_EV_CONN_RSEC, qc); + if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { + TRACE_PROTO("CC required", QUIC_EV_CONN_RSEC, qc); goto out; } @@ -864,11 +862,11 @@ int ha_set_rsec(SSL *ssl, enum ssl_encryption_level_t level, tls_ctx->rx.iv, tls_ctx->rx.ivlen, tls_ctx->rx.hp_key, sizeof tls_ctx->rx.hp_key, secret, secret_len)) { - TRACE_DEVEL("RX key derivation failed", QUIC_EV_CONN_RSEC, conn->qc); + TRACE_DEVEL("RX key derivation failed", QUIC_EV_CONN_RSEC, qc); goto err; } - if (objt_server(conn->target) && level == ssl_encryption_application) { + if (!qc_is_listener(qc) && level == ssl_encryption_application) { const unsigned char *buf; size_t buflen; @@ -876,18 +874,18 @@ int ha_set_rsec(SSL *ssl, enum ssl_encryption_level_t level, if (!buflen) goto err; - if (!quic_transport_params_store(conn->qc, 1, buf, buf + buflen)) + if (!quic_transport_params_store(qc, 1, buf, buf + buflen)) goto err; } tls_ctx->rx.flags |= QUIC_FL_TLS_SECRETS_SET; out: - TRACE_LEAVE(QUIC_EV_CONN_RSEC, conn->qc, &level, secret, &secret_len); + TRACE_LEAVE(QUIC_EV_CONN_RSEC, qc, &level, secret, &secret_len); return 1; err: - TRACE_DEVEL("leaving in error", QUIC_EV_CONN_RSEC, conn->qc); + TRACE_DEVEL("leaving in error", QUIC_EV_CONN_RSEC, qc); return 0; } @@ -899,13 +897,12 @@ int ha_set_wsec(SSL *ssl, enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); - struct quic_tls_ctx *tls_ctx = - &conn->qc->els[ssl_to_quic_enc_level(level)].tls_ctx; + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); + struct quic_tls_ctx *tls_ctx = &qc->els[ssl_to_quic_enc_level(level)].tls_ctx; - TRACE_ENTER(QUIC_EV_CONN_WSEC, conn->qc); - if (HA_ATOMIC_LOAD(&conn->qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { - TRACE_PROTO("CC required", QUIC_EV_CONN_WSEC, conn->qc); + TRACE_ENTER(QUIC_EV_CONN_WSEC, qc); + if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { + TRACE_PROTO("CC required", QUIC_EV_CONN_WSEC, qc); goto out; } @@ -921,17 +918,17 @@ int ha_set_wsec(SSL *ssl, enum ssl_encryption_level_t level, tls_ctx->tx.iv, tls_ctx->tx.ivlen, tls_ctx->tx.hp_key, sizeof tls_ctx->tx.hp_key, secret, secret_len)) { - TRACE_DEVEL("TX key derivation failed", QUIC_EV_CONN_WSEC, conn->qc); + TRACE_DEVEL("TX key derivation failed", QUIC_EV_CONN_WSEC, qc); goto err; } tls_ctx->tx.flags |= QUIC_FL_TLS_SECRETS_SET; - TRACE_LEAVE(QUIC_EV_CONN_WSEC, conn->qc, &level, secret, &secret_len); + TRACE_LEAVE(QUIC_EV_CONN_WSEC, qc, &level, secret, &secret_len); out: return 1; err: - TRACE_DEVEL("leaving in error", QUIC_EV_CONN_WSEC, conn->qc); + TRACE_DEVEL("leaving in error", QUIC_EV_CONN_WSEC, qc); return 0; } #endif @@ -1071,59 +1068,59 @@ int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alp int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level, const uint8_t *data, size_t len) { - struct connection *conn; + struct quic_conn *qc; enum quic_tls_enc_level tel; struct quic_enc_level *qel; - conn = SSL_get_ex_data(ssl, ssl_app_data_index); - TRACE_ENTER(QUIC_EV_CONN_ADDDATA, conn->qc); - if (HA_ATOMIC_LOAD(&conn->qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { - TRACE_PROTO("CC required", QUIC_EV_CONN_ADDDATA, conn->qc); + qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); + TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc); + if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IMMEDIATE_CLOSE) { + TRACE_PROTO("CC required", QUIC_EV_CONN_ADDDATA, qc); goto out; } tel = ssl_to_quic_enc_level(level); - qel = &conn->qc->els[tel]; + qel = &qc->els[tel]; if (tel == -1) { - TRACE_PROTO("Wrong encryption level", QUIC_EV_CONN_ADDDATA, conn->qc); + TRACE_PROTO("Wrong encryption level", QUIC_EV_CONN_ADDDATA, qc); goto err; } if (!quic_crypto_data_cpy(qel, data, len)) { - TRACE_PROTO("Could not bufferize", QUIC_EV_CONN_ADDDATA, conn->qc); + TRACE_PROTO("Could not bufferize", QUIC_EV_CONN_ADDDATA, qc); goto err; } TRACE_PROTO("CRYPTO data buffered", QUIC_EV_CONN_ADDDATA, - conn->qc, &level, &len); + qc, &level, &len); out: - TRACE_LEAVE(QUIC_EV_CONN_ADDDATA, conn->qc); + TRACE_LEAVE(QUIC_EV_CONN_ADDDATA, qc); return 1; err: - TRACE_DEVEL("leaving in error", QUIC_EV_CONN_ADDDATA, conn->qc); + TRACE_DEVEL("leaving in error", QUIC_EV_CONN_ADDDATA, qc); return 0; } int ha_quic_flush_flight(SSL *ssl) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); - TRACE_ENTER(QUIC_EV_CONN_FFLIGHT, conn->qc); - TRACE_LEAVE(QUIC_EV_CONN_FFLIGHT, conn->qc); + TRACE_ENTER(QUIC_EV_CONN_FFLIGHT, qc); + TRACE_LEAVE(QUIC_EV_CONN_FFLIGHT, qc); return 1; } int ha_quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert) { - struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); + struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index); - TRACE_DEVEL("SSL alert", QUIC_EV_CONN_SSLALERT, conn->qc, &alert, &level); - quic_set_tls_alert(conn->qc, alert); - HA_ATOMIC_STORE(&conn->qc->flags, QUIC_FL_CONN_IMMEDIATE_CLOSE); + TRACE_DEVEL("SSL alert", QUIC_EV_CONN_SSLALERT, qc, &alert, &level); + quic_set_tls_alert(qc, alert); + HA_ATOMIC_STORE(&qc->flags, QUIC_FL_CONN_IMMEDIATE_CLOSE); return 1; } @@ -5384,7 +5381,7 @@ static int qc_ssl_sess_init(struct quic_conn *qc, SSL_CTX *ssl_ctx, SSL **ssl, } if (!SSL_set_quic_method(*ssl, &ha_quic_method) || - !SSL_set_ex_data(*ssl, ssl_app_data_index, qc->conn) || + !SSL_set_ex_data(*ssl, ssl_qc_app_data_index, qc) || !SSL_set_quic_transport_params(*ssl, qc->enc_params, qc->enc_params_len)) { goto err;