537 lines
17 KiB
Diff
537 lines
17 KiB
Diff
diff --git a/include/internal/quic_cfq.h b/include/internal/quic_cfq.h
|
|
index 0b2a3a4cb2d..96c8d89eb60 100644
|
|
--- a/include/internal/quic_cfq.h
|
|
+++ b/include/internal/quic_cfq.h
|
|
@@ -149,6 +149,7 @@ QUIC_CFQ_ITEM *ossl_quic_cfq_get_priority_head(const QUIC_CFQ *cfq,
|
|
QUIC_CFQ_ITEM *ossl_quic_cfq_item_get_priority_next(const QUIC_CFQ_ITEM *item,
|
|
uint32_t pn_space);
|
|
|
|
+int ossl_quic_cfq_discard_unreliable(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item);
|
|
#endif
|
|
|
|
#endif
|
|
diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h
|
|
index b08e63e148a..d333bc3e5e5 100644
|
|
--- a/include/internal/quic_channel.h
|
|
+++ b/include/internal/quic_channel.h
|
|
@@ -466,6 +466,9 @@ uint64_t ossl_quic_channel_get_max_idle_timeout_actual(const QUIC_CHANNEL *ch);
|
|
const QUIC_CONN_ID *scid, const QUIC_CONN_ID *dcid,
|
|
const QUIC_CONN_ID *odcid);
|
|
|
|
+void ossl_ch_reset_rx_state(QUIC_CHANNEL *ch);
|
|
+uint64_t ossl_quic_channel_get_path_challenge_count(const QUIC_CHANNEL *ch);
|
|
+uint64_t ossl_quic_channel_get_path_response_count(const QUIC_CHANNEL *ch);
|
|
#endif
|
|
|
|
#endif
|
|
diff --git a/include/internal/quic_fifd.h b/include/internal/quic_fifd.h
|
|
index 4ea7a2e0d22..afa330cbc4a 100644
|
|
--- a/include/internal/quic_fifd.h
|
|
+++ b/include/internal/quic_fifd.h
|
|
@@ -83,6 +83,7 @@ int ossl_quic_fifd_pkt_commit(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *pkt);
|
|
void ossl_quic_fifd_set_qlog_cb(QUIC_FIFD *fifd, QLOG *(*get_qlog_cb)(void *arg),
|
|
void *arg);
|
|
|
|
+void ossl_quic_fifd_pkt_discard_unreliable(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *tpkt);
|
|
#endif
|
|
|
|
#endif
|
|
diff --git a/ssl/quic/quic_cfq.c b/ssl/quic/quic_cfq.c
|
|
index 3c59234ff0f..16818e55f57 100644
|
|
--- a/ssl/quic/quic_cfq.c
|
|
+++ b/ssl/quic/quic_cfq.c
|
|
@@ -7,6 +7,7 @@
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
+#include "internal/quic_channel.h"
|
|
#include "internal/quic_cfq.h"
|
|
#include "internal/numbers.h"
|
|
|
|
@@ -307,6 +308,20 @@ void ossl_quic_cfq_mark_lost(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item,
|
|
}
|
|
}
|
|
|
|
+int ossl_quic_cfq_discard_unreliable(QUIC_CFQ *cfq, QUIC_CFQ_ITEM *item)
|
|
+{
|
|
+ int discarded;
|
|
+
|
|
+ if (ossl_quic_cfq_item_is_unreliable(item)) {
|
|
+ ossl_quic_cfq_release(cfq, item);
|
|
+ discarded = 1;
|
|
+ } else {
|
|
+ discarded = 0;
|
|
+ }
|
|
+
|
|
+ return discarded;
|
|
+}
|
|
+
|
|
/*
|
|
* Releases a CFQ item. The item may be in either state (NEW or TX) prior to the
|
|
* call. The QUIC_CFQ_ITEM pointer must not be used following this call.
|
|
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
|
|
index 631f289b391..9534cbcaf7f 100644
|
|
--- a/ssl/quic/quic_channel.c
|
|
+++ b/ssl/quic/quic_channel.c
|
|
@@ -2213,6 +2213,12 @@ static void ch_rx_check_forged_pkt_limit(QUIC_CHANNEL *ch)
|
|
"forgery limit");
|
|
}
|
|
|
|
+void ossl_ch_reset_rx_state(QUIC_CHANNEL *ch)
|
|
+{
|
|
+ ch->did_crypto_frame = 0;
|
|
+ ch->seen_path_challenge = 0;
|
|
+}
|
|
+
|
|
/* Process queued incoming packets and handle frames, if any. */
|
|
static int ch_rx(QUIC_CHANNEL *ch, int channel_only, int *notify_other_threads)
|
|
{
|
|
@@ -4060,3 +4066,13 @@ uint64_t ossl_quic_channel_get_max_idle_timeout_actual(const QUIC_CHANNEL *ch)
|
|
{
|
|
return ch->max_idle_timeout;
|
|
}
|
|
+
|
|
+uint64_t ossl_quic_channel_get_path_challenge_count(const QUIC_CHANNEL *ch)
|
|
+{
|
|
+ return ch->path_challenge_rx;
|
|
+}
|
|
+
|
|
+uint64_t ossl_quic_channel_get_path_response_count(const QUIC_CHANNEL *ch)
|
|
+{
|
|
+ return ch->path_response_tx;
|
|
+}
|
|
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
|
|
index ae443fccca1..eb082d6cea7 100644
|
|
--- a/ssl/quic/quic_channel_local.h
|
|
+++ b/ssl/quic/quic_channel_local.h
|
|
@@ -12,6 +12,28 @@
|
|
#include "internal/quic_stream_map.h"
|
|
#include "internal/quic_tls.h"
|
|
|
|
+/*
|
|
+ * This is a part of PATH_CHALLENGE flood [1] mitigation. This limits the
|
|
+ * number of PATH_CHALLENGE frames QUIC stack is willing to process for
|
|
+ * connection. Local QUIC stack creates PATH_RESPONSE frame for PATH_CHALLENGE
|
|
+ * frame it receives from remote peer. The response frame is put Control Frame
|
|
+ * Queue waiting to be dispatched. The PATH_RESPONSE frame is removed from CFQ
|
|
+ * after it is dispatched. The QUIC_PATH_RESPONSE_QLEN limits the number of
|
|
+ * PATH_RESPONSE frames waiting to be dispatched. No new PATH_RESPONSE frames
|
|
+ * are inserted into CFQ if queue limit is exceeded.
|
|
+ *
|
|
+ * QUIC implementations use different limits for PATH_RESPONSE queue lengths:
|
|
+ * quic-go defines maxPathResponses as 256
|
|
+ * quiche from cloadflare sets DEFAULT_MAX_PATH_CHALLENGE_RX_QUEUE_LEN to 3
|
|
+ * t-quic from tencent chooses MAX_PATH_CHALS_RECV to be 8
|
|
+ *
|
|
+ * OpenSSL here introduces QUIC_PATH_RESPONSE_QLEN as 32.
|
|
+ *
|
|
+ * [1] https://www.ietf.org/archive/id/draft-chen-quic-logical-vuln-mitigations-00.txt
|
|
+ * (section 4.2)
|
|
+ */
|
|
+#define QUIC_PATH_RESPONSE_QLEN 32
|
|
+
|
|
/*
|
|
* QUIC Channel Structure
|
|
* ======================
|
|
@@ -457,6 +479,18 @@ struct quic_channel_st {
|
|
|
|
/* Has qlog been requested? */
|
|
unsigned int is_tserver_ch : 1;
|
|
+ /*
|
|
+ * RFC 9000 Section 9.2.1 says:
|
|
+ * However, an endpoint SHOULD NOT send multiple
|
|
+ * PATH_CHALLENGE frames in a single packet.
|
|
+ * The counter here allows us to detect multiple presence
|
|
+ * of PATH_CHALLENGE frame in packet. We process only the
|
|
+ * first PATH_CHALLENGE frame found in packet. Remaining PATH_CHALLENGE
|
|
+ * frames are ignored.
|
|
+ * seen_path_challenge flag is always reset before
|
|
+ * ossl_quic_handle_frames() gets called.
|
|
+ */
|
|
+ unsigned int seen_path_challenge : 1;
|
|
|
|
/* Saved error stack in case permanent error was encountered */
|
|
ERR_STATE *err_state;
|
|
@@ -467,6 +501,15 @@ struct quic_channel_st {
|
|
|
|
/* Title for qlog purposes. We own this copy. */
|
|
char *qlog_title;
|
|
+ /*
|
|
+ * number of path responses waiting to be dispatched
|
|
+ * from control frame queue (CFQ)
|
|
+ */
|
|
+ unsigned int path_response_limit;
|
|
+ /* number of path challenge frames received */
|
|
+ unsigned int path_challenge_rx;
|
|
+ /* number of path response frames sent */
|
|
+ unsigned int path_response_tx;
|
|
};
|
|
|
|
#endif
|
|
diff --git a/ssl/quic/quic_fifd.c b/ssl/quic/quic_fifd.c
|
|
index 03b8cebd305..e80483b501d 100644
|
|
--- a/ssl/quic/quic_fifd.c
|
|
+++ b/ssl/quic/quic_fifd.c
|
|
@@ -310,3 +310,46 @@ void ossl_quic_fifd_set_qlog_cb(QUIC_FIFD *fifd, QLOG *(*get_qlog_cb)(void *arg)
|
|
fifd->get_qlog_cb = get_qlog_cb;
|
|
fifd->get_qlog_cb_arg = get_qlog_cb_arg;
|
|
}
|
|
+
|
|
+static void txpim_pkt_remove_cfq_item(QUIC_TXPIM_PKT *pkt, QUIC_CFQ_ITEM *cfq_item)
|
|
+{
|
|
+ QUIC_CFQ_ITEM *prev = cfq_item->pkt_prev;
|
|
+
|
|
+ if (prev != NULL) {
|
|
+ prev->pkt_next = cfq_item->pkt_next;
|
|
+ } else {
|
|
+ pkt->retx_head = cfq_item->pkt_next;
|
|
+ }
|
|
+
|
|
+ if (cfq_item->pkt_next != NULL)
|
|
+ cfq_item->pkt_next->pkt_prev = prev;
|
|
+
|
|
+ cfq_item->pkt_prev = NULL;
|
|
+ cfq_item->pkt_next = NULL;
|
|
+}
|
|
+
|
|
+void ossl_quic_fifd_pkt_discard_unreliable(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *pkt)
|
|
+{
|
|
+ QUIC_CFQ_ITEM *cfq_item, *cfq_next;
|
|
+
|
|
+ /*
|
|
+ * The packet has been written to network. We can discard frames we don't
|
|
+ * retransmit when loss is detected.
|
|
+ */
|
|
+ cfq_item = pkt->retx_head;
|
|
+ while (cfq_item != NULL) {
|
|
+ /*
|
|
+ * Discarded items are moved to free list. If item
|
|
+ * got moved to free list we must also remove it from
|
|
+ * cfq list kept in pkt, so ACKM does not find it when
|
|
+ * receives an ACK for pkt.
|
|
+ */
|
|
+ if (ossl_quic_cfq_discard_unreliable(fifd->cfq, cfq_item)) {
|
|
+ cfq_next = cfq_item->pkt_next;
|
|
+ txpim_pkt_remove_cfq_item(pkt, cfq_item);
|
|
+ cfq_item = cfq_next;
|
|
+ } else {
|
|
+ cfq_item = cfq_item->pkt_next;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c
|
|
index 786af9b4c22..7ab59f01a1c 100644
|
|
--- a/ssl/quic/quic_rx_depack.c
|
|
+++ b/ssl/quic/quic_rx_depack.c
|
|
@@ -931,6 +931,22 @@ static int depack_do_frame_retire_conn_id(PACKET *pkt,
|
|
|
|
static void free_path_response(unsigned char *buf, size_t buf_len, void *arg)
|
|
{
|
|
+ QUIC_CHANNEL *ch = (QUIC_CHANNEL *)arg;
|
|
+
|
|
+ assert(ch->path_response_limit > 0);
|
|
+
|
|
+ ch->path_response_limit--;
|
|
+
|
|
+ /*
|
|
+ * Assume path response frame is being freed on behalf of
|
|
+ * finished TX operation. This is for unit testing purposes
|
|
+ * only. The counter is also bumped when channel is being
|
|
+ * destroyed and CFQ (control frame queue) is freed.
|
|
+ * This currently does not matter for check_pc_flood
|
|
+ * in test/radix/quic_tests.c.
|
|
+ */
|
|
+ ch->path_response_tx++;
|
|
+
|
|
OPENSSL_free(buf);
|
|
}
|
|
|
|
@@ -951,33 +967,41 @@ static int depack_do_frame_path_challenge(PACKET *pkt,
|
|
return 0;
|
|
}
|
|
|
|
- /*
|
|
- * RFC 9000 s. 8.2.2: On receiving a PATH_CHALLENGE frame, an endpoint MUST
|
|
- * respond by echoing the data contained in the PATH_CHALLENGE frame in a
|
|
- * PATH_RESPONSE frame.
|
|
- *
|
|
- * TODO(QUIC FUTURE): We should try to avoid allocation here in the future.
|
|
- */
|
|
- encoded_len = sizeof(uint64_t) + 1;
|
|
- if ((encoded = OPENSSL_malloc(encoded_len)) == NULL)
|
|
- goto err;
|
|
+ if (ch->seen_path_challenge == 0
|
|
+ && ch->path_response_limit < QUIC_PATH_RESPONSE_QLEN) {
|
|
+ /*
|
|
+ * RFC 9000 s. 8.2.2: On receiving a PATH_CHALLENGE frame, an endpoint
|
|
+ * MUST respond by echoing the data contained in the PATH_CHALLENGE
|
|
+ * frame in a PATH_RESPONSE frame.
|
|
+ *
|
|
+ * TODO(QUIC FUTURE): We should try to avoid allocation here in the
|
|
+ * future.
|
|
+ */
|
|
+ encoded_len = sizeof(uint64_t) + 1;
|
|
+ if ((encoded = OPENSSL_malloc(encoded_len)) == NULL)
|
|
+ goto err;
|
|
|
|
- if (!WPACKET_init_static_len(&wpkt, encoded, encoded_len, 0))
|
|
- goto err;
|
|
+ if (!WPACKET_init_static_len(&wpkt, encoded, encoded_len, 0))
|
|
+ goto err;
|
|
|
|
- if (!ossl_quic_wire_encode_frame_path_response(&wpkt, frame_data)) {
|
|
- WPACKET_cleanup(&wpkt);
|
|
- goto err;
|
|
- }
|
|
+ if (!ossl_quic_wire_encode_frame_path_response(&wpkt, frame_data)) {
|
|
+ WPACKET_cleanup(&wpkt);
|
|
+ goto err;
|
|
+ }
|
|
|
|
- WPACKET_finish(&wpkt);
|
|
+ WPACKET_finish(&wpkt);
|
|
|
|
- if (!ossl_quic_cfq_add_frame(ch->cfq, 0, QUIC_PN_SPACE_APP,
|
|
- OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
|
|
- QUIC_CFQ_ITEM_FLAG_UNRELIABLE,
|
|
- encoded, encoded_len,
|
|
- free_path_response, NULL))
|
|
- goto err;
|
|
+ if (!ossl_quic_cfq_add_frame(ch->cfq, 0, QUIC_PN_SPACE_APP,
|
|
+ OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
|
|
+ QUIC_CFQ_ITEM_FLAG_UNRELIABLE,
|
|
+ encoded, encoded_len,
|
|
+ free_path_response, ch))
|
|
+ goto err;
|
|
+ ch->seen_path_challenge = 1;
|
|
+ ch->path_response_limit++;
|
|
+ }
|
|
+
|
|
+ ch->path_challenge_rx++;
|
|
|
|
return 1;
|
|
|
|
@@ -1432,7 +1456,7 @@ int ossl_quic_handle_frames(QUIC_CHANNEL *ch, OSSL_QRX_PKT *qpacket)
|
|
if (ch == NULL)
|
|
return 0;
|
|
|
|
- ch->did_crypto_frame = 0;
|
|
+ ossl_ch_reset_rx_state(ch);
|
|
|
|
/* Initialize |ackm_data| (and reinitialize |ok|)*/
|
|
memset(&ackm_data, 0, sizeof(ackm_data));
|
|
diff --git a/ssl/quic/quic_txp.c b/ssl/quic/quic_txp.c
|
|
index 44aaad868d2..b2565c1a9fe 100644
|
|
--- a/ssl/quic/quic_txp.c
|
|
+++ b/ssl/quic/quic_txp.c
|
|
@@ -3133,6 +3133,8 @@ static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp,
|
|
--probe_info->pto[pn_space];
|
|
}
|
|
|
|
+ ossl_quic_fifd_pkt_discard_unreliable(&txp->fifd, tpkt);
|
|
+
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c
|
|
index 181ba1226b8..48b1df6c1d4 100644
|
|
--- a/test/radix/quic_tests.c
|
|
+++ b/test/radix/quic_tests.c
|
|
@@ -294,6 +294,188 @@ DEF_SCRIPT(check_cwm, "check stream obeys cwm")
|
|
OP_WRITE_FAIL(C);
|
|
}
|
|
|
|
+struct mutcbk_ctx {
|
|
+ QUIC_PKT_HDR mutctx_qhdrin;
|
|
+ OSSL_QTX_IOVEC mutctx_iov;
|
|
+ const unsigned char *mutctx_inject;
|
|
+ size_t mutctx_inject_sz;
|
|
+ int mutctx_done;
|
|
+};
|
|
+
|
|
+static int mutcbk_inject_frames(const QUIC_PKT_HDR *hdrin,
|
|
+ const OSSL_QTX_IOVEC *iovecin, size_t numin, QUIC_PKT_HDR **hdrout,
|
|
+ const OSSL_QTX_IOVEC **iovecout, size_t *numout, void *arg)
|
|
+{
|
|
+ struct mutcbk_ctx *mutctx = (struct mutcbk_ctx *)arg;
|
|
+ size_t i;
|
|
+ size_t grow_allowance = 1200; /* QUIC_MIN_INITIAL_DGRAM_LEN */
|
|
+ size_t bufsz = 0;
|
|
+ char *buf;
|
|
+
|
|
+ /*
|
|
+ * make injection callback a one shot event,
|
|
+ * callback is invoked for every packet we
|
|
+ * want to modify only one packet here.
|
|
+ */
|
|
+ if (mutctx->mutctx_done)
|
|
+ return 0;
|
|
+
|
|
+ mutctx->mutctx_done = 1;
|
|
+
|
|
+ for (i = 0; i < numin; i++)
|
|
+ bufsz += iovecin[i].buf_len;
|
|
+
|
|
+ mutctx->mutctx_iov.buf_len = bufsz; /* keeps old size */
|
|
+ grow_allowance -= (bufsz < grow_allowance) ? bufsz : grow_allowance;
|
|
+ /* AEAD tag (16 bytes) + long header (14 bytes) */
|
|
+ grow_allowance -= (30 < grow_allowance) ? 30 : grow_allowance;
|
|
+
|
|
+ grow_allowance -= (hdrin->dst_conn_id.id_len < grow_allowance) ? hdrin->dst_conn_id.id_len : grow_allowance;
|
|
+ grow_allowance -= (hdrin->src_conn_id.id_len < grow_allowance) ? hdrin->src_conn_id.id_len : grow_allowance;
|
|
+
|
|
+ if (grow_allowance == 0) {
|
|
+ TEST_info("mutcbk_inject_frames() not enough space to inject");
|
|
+ return 0;
|
|
+ }
|
|
+ bufsz += grow_allowance;
|
|
+
|
|
+ /* discard const */
|
|
+ OPENSSL_free((char *)mutctx->mutctx_iov.buf);
|
|
+ mutctx->mutctx_iov.buf = OPENSSL_malloc(bufsz);
|
|
+ /* discard const */
|
|
+ buf = (char *)mutctx->mutctx_iov.buf;
|
|
+ if (buf == NULL) {
|
|
+ TEST_info("mutcbk_inject_frames() OPENSSL_malloc() failed");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < numin; i++) {
|
|
+ memcpy(buf, iovecin[i].buf, iovecin[i].buf_len);
|
|
+ buf += iovecin[i].buf_len;
|
|
+ }
|
|
+
|
|
+ /* discard const */
|
|
+ buf = (char *)mutctx->mutctx_iov.buf;
|
|
+ if (mutctx->mutctx_inject != NULL) {
|
|
+ memmove(buf + mutctx->mutctx_inject_sz, buf,
|
|
+ mutctx->mutctx_iov.buf_len);
|
|
+ memcpy(buf, mutctx->mutctx_inject, mutctx->mutctx_inject_sz);
|
|
+ }
|
|
+ /*
|
|
+ * perhaps needed to have not looked at yet
|
|
+ */
|
|
+ mutctx->mutctx_qhdrin = *hdrin;
|
|
+ *hdrout = &mutctx->mutctx_qhdrin;
|
|
+ mutctx->mutctx_iov.buf_len += mutctx->mutctx_inject_sz;
|
|
+ *iovecout = &mutctx->mutctx_iov;
|
|
+ *numout = 1;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static void mutcbk_finish_injecct_frames(void *arg)
|
|
+{
|
|
+ struct mutcbk_ctx *mutctx = (struct mutcbk_ctx *)arg;
|
|
+
|
|
+ OPENSSL_free((char *)mutctx->mutctx_iov.buf);
|
|
+ mutctx->mutctx_iov.buf = NULL;
|
|
+}
|
|
+
|
|
+/* 16 path challenge frames */
|
|
+#define PATH_CHALLENGE_FRAMES \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH" \
|
|
+ "\x1a" \
|
|
+ "ABCDEFGH"
|
|
+
|
|
+DEF_FUNC(mount_flood)
|
|
+{
|
|
+ int ok = 0;
|
|
+ SSL *ssl;
|
|
+ QUIC_CHANNEL *ch;
|
|
+ static struct mutcbk_ctx mutctx = { 0 };
|
|
+ static const unsigned char *inject_frames = (const unsigned char *)PATH_CHALLENGE_FRAMES;
|
|
+
|
|
+ mutctx.mutctx_inject = inject_frames;
|
|
+ mutctx.mutctx_inject_sz = sizeof(PATH_CHALLENGE_FRAMES) - 1;
|
|
+ REQUIRE_SSL(ssl);
|
|
+ ch = ossl_quic_conn_get_channel(ssl);
|
|
+ if (!TEST_ptr(ch))
|
|
+ goto err;
|
|
+
|
|
+ if (!TEST_true(ossl_quic_channel_set_mutator(ch, mutcbk_inject_frames,
|
|
+ mutcbk_finish_injecct_frames, &mutctx)))
|
|
+ goto err;
|
|
+ ok = 1;
|
|
+err:
|
|
+ return ok;
|
|
+}
|
|
+
|
|
+DEF_FUNC(check_flood_stats)
|
|
+{
|
|
+ int ok = 0;
|
|
+ SSL *ssl;
|
|
+ QUIC_CHANNEL *ch;
|
|
+ uint64_t path_response_count;
|
|
+ uint64_t path_challenge_count;
|
|
+
|
|
+ REQUIRE_SSL(ssl);
|
|
+ ch = ossl_quic_conn_get_channel(ssl);
|
|
+ if (!TEST_ptr(ch))
|
|
+ goto err;
|
|
+
|
|
+ path_challenge_count = ossl_quic_channel_get_path_challenge_count(ch);
|
|
+ path_response_count = ossl_quic_channel_get_path_response_count(ch);
|
|
+
|
|
+ if (TEST_uint64_t_ne(path_challenge_count, 16))
|
|
+ goto err;
|
|
+ if (TEST_uint64_t_ne(path_response_count, 1))
|
|
+ goto err;
|
|
+
|
|
+ ok = 1;
|
|
+err:
|
|
+ return ok;
|
|
+}
|
|
+
|
|
+DEF_SCRIPT(check_pc_flood, "check path challenge flood")
|
|
+{
|
|
+ OP_SIMPLE_PAIR_CONN();
|
|
+ OP_SELECT_SSL(0, C);
|
|
+ OP_FUNC(mount_flood);
|
|
+ OP_ACCEPT_CONN_WAIT(L, S, 0);
|
|
+ OP_WRITE_B(C, "attack");
|
|
+ OP_SELECT_SSL(0, S);
|
|
+ OP_FUNC(check_flood_stats);
|
|
+}
|
|
+
|
|
/*
|
|
* List of Test Scripts
|
|
* ============================================================================
|
|
@@ -302,5 +484,6 @@ static SCRIPT_INFO *const scripts[] = {
|
|
USE(simple_conn)
|
|
USE(simple_thread)
|
|
USE(ssl_poll)
|
|
- USE(check_cwm)
|
|
+ USE(check_cwm)
|
|
+ USE(check_pc_flood)
|
|
};
|