]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Drop packets with STREAM frames with wrong direction.
authorFrédéric Lécaille <flecaille@haproxy.com>
Thu, 31 Dec 2020 11:45:38 +0000 (12:45 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 4 Jan 2021 11:31:28 +0000 (12:31 +0100)
A server initiates streams with odd-numbered stream IDs.
Also add useful traces when parsing STREAM frames.

include/haproxy/quic_frame-t.h
include/haproxy/xprt_quic-t.h
src/quic_frame.c
src/xprt_quic.c

index 855a37ecf1f390348caa58730a1536e0404dec8f..6a3226e3ee1b9df1c01abb5e562ada71e583f468 100644 (file)
@@ -88,9 +88,14 @@ enum quic_frame_type {
 
 #define QUIC_FT_PKT_TYPE____1_BITMASK QUIC_FT_PKT_TYPE_1_BITMASK
 
-#define QUIC_STREAM_FRAME_FIN_BIT    0x01
-#define QUIC_STREAM_FRAME_LEN_BIT    0x02
-#define QUIC_STREAM_FRAME_OFF_BIT    0x04
+#define QUIC_STREAM_FRAME_TYPE_FIN_BIT     0x01
+#define QUIC_STREAM_FRAME_TYPE_LEN_BIT     0x02
+#define QUIC_STREAM_FRAME_TYPE_OFF_BIT     0x04
+
+/* Servers have the stream initiator bit set. */
+#define QUIC_STREAM_FRAME_ID_INITIATOR_BIT 0x01
+/* Unidirectional streams have the direction bit set. */
+#define QUIC_STREAM_FRAME_ID_DIR_BIT       0x02
 
 #define QUIC_PATH_CHALLENGE_LEN         8
 
index bb05c54472466671b9fa675e9a13d154994d71d7..6cf9fae3b8aeca5969d09a080bbe35b6dc94de9a 100644 (file)
@@ -201,6 +201,7 @@ enum quic_pkt_type {
 #define           QUIC_EV_CONN_ADDDATA   (1ULL << 25)
 #define           QUIC_EV_CONN_FFLIGHT   (1ULL << 26)
 #define           QUIC_EV_CONN_SSLALERT  (1ULL << 27)
+#define           QUIC_EV_CONN_PSTRM     (1ULL << 28)
 #define           QUIC_EV_CONN_RTTUPDT   (1ULL << 29)
 #define           QUIC_EV_CONN_CC        (1ULL << 30)
 #define           QUIC_EV_CONN_SPPKTS    (1ULL << 31)
index d80eb5ac4ef6b0015e286bc4e4583115cc04ffec..59478569ae82e0fc3eb8b15bbdb0dbc0ddc4b5fa 100644 (file)
@@ -377,8 +377,8 @@ static int quic_build_stream_frame(unsigned char **buf, const unsigned char *end
        struct quic_stream *stream = &frm->stream;
 
        if (!quic_enc_int(buf, end, stream->id) ||
-           ((frm->type & QUIC_STREAM_FRAME_OFF_BIT) && !quic_enc_int(buf, end, stream->offset)) ||
-           ((frm->type & QUIC_STREAM_FRAME_LEN_BIT) &&
+           ((frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) && !quic_enc_int(buf, end, stream->offset)) ||
+           ((frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) &&
             (!quic_enc_int(buf, end, stream->len) || end - *buf < stream->len)))
                return 0;
 
@@ -400,14 +400,14 @@ static int quic_parse_stream_frame(struct quic_frame *frm, struct quic_conn *qc,
                return 0;
 
        /* Offset parsing */
-       if (!(frm->type & QUIC_STREAM_FRAME_OFF_BIT)) {
+       if (!(frm->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT)) {
                stream->offset = 0;
        }
        else if (!quic_dec_int(&stream->offset, buf, end))
                return 0;
 
        /* Length parsing */
-       if (!(frm->type & QUIC_STREAM_FRAME_LEN_BIT)) {
+       if (!(frm->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT)) {
                stream->len = end - *buf;
        }
        else if (!quic_dec_int(&stream->len, buf, end) || end - *buf < stream->len)
index 97160ab8e3f56879e856262311dc9fb25a543e13..c20d877c3930bc04491bd16f5f3ee419caf2ec7c 100644 (file)
@@ -571,6 +571,18 @@ static void quic_trace(enum trace_level level, uint64_t mask, const struct trace
                        if (sz3)
                                chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz3);
                }
+
+               if (mask & QUIC_EV_CONN_PSTRM) {
+                       const struct quic_frame *frm = a2;
+                       const struct quic_stream *s = &frm->stream;
+
+                       chunk_appendf(&trace_buf, " uni=%d fin=%d id=%llu off=%llu len=%llu",
+                                     !!(s->id & QUIC_STREAM_FRAME_ID_DIR_BIT),
+                                     !!(frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT),
+                                     (unsigned long long)s->id,
+                                     (unsigned long long)s->offset,
+                                     (unsigned long long)s->len);
+               }
        }
        if (mask & QUIC_EV_CONN_LPKT) {
                const struct quic_rx_packet *pkt = a2;
@@ -1642,6 +1654,17 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct quic_conn_ctx *c
                case QUIC_FT_STREAM_D:
                case QUIC_FT_STREAM_E:
                case QUIC_FT_STREAM_F:
+               {
+                       struct quic_stream *stream = &frm.stream;
+
+                       TRACE_PROTO("STREAM frame", QUIC_EV_CONN_PSTRM, ctx->conn, &frm);
+                       if (objt_listener(ctx->conn->target)) {
+                               if (stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT)
+                                       goto err;
+                       } else if (!(stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT))
+                               goto err;
+                       break;
+               }
                case QUIC_FT_NEW_CONNECTION_ID:
                        break;
                case QUIC_FT_CONNECTION_CLOSE: