From d2001ef94b70dabae28ad921cb40691771afa67c Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Mon, 9 Jan 2023 08:05:37 +0100 Subject: [PATCH] stream: improve gap tests --- src/stream-tcp-reassemble.c | 88 ++++++++++++++++++++++++++++++++--- src/tests/stream-tcp-inline.c | 69 ++++++++++++++++++++------- 2 files changed, 134 insertions(+), 23 deletions(-) diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 6178181a3e..ce5f90309b 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -2206,6 +2206,63 @@ static int VALIDATE(TcpStream *stream, uint8_t *data, uint32_t data_len) StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); \ FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen)))); +#define MISSED_ADD_PAYLOAD(seq, seg, seglen) \ + StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)); + +int UTHCheckGapAtPostion(TcpStream *stream, int pos, uint64_t offset, uint32_t len); + +int UTHCheckGapAtPostion(TcpStream *stream, int pos, uint64_t offset, uint32_t len) +{ + int cnt = 0; + uint64_t last_re = 0; + StreamingBufferBlock *sbb = NULL; + RB_FOREACH(sbb, SBB, &stream->sb.sbb_tree) + { + if (sbb->offset != last_re) { + // gap before us + if (cnt == pos && last_re == offset && len == sbb->offset - last_re) { + return 1; + } + cnt++; + } + last_re = sbb->offset + sbb->len; + cnt++; + } + return 0; +} + +int UTHCheckDataAtPostion( + TcpStream *stream, int pos, uint64_t offset, const char *data, uint32_t len); + +int UTHCheckDataAtPostion( + TcpStream *stream, int pos, uint64_t offset, const char *data, uint32_t len) +{ + int cnt = 0; + uint64_t last_re = 0; + StreamingBufferBlock *sbb = NULL; + RB_FOREACH(sbb, SBB, &stream->sb.sbb_tree) + { + if (sbb->offset != last_re) { + // gap before us + cnt++; + } + + if (cnt == pos && sbb->offset == offset) { + const uint8_t *buf = NULL; + uint32_t buf_len = 0; + StreamingBufferSBBGetData(&stream->sb, sbb, &buf, &buf_len); + + if (len == buf_len) { + return (memcmp(data, buf, len) == 0); + } + } + + last_re = sbb->offset + sbb->len; + cnt++; + } + return 0; +} + /** * \test Test the handling of packets missed by both IDS and the end host. * The packet is missed in the starting of the stream. @@ -2216,10 +2273,15 @@ static int VALIDATE(TcpStream *stream, uint8_t *data, uint32_t data_len) static int StreamTcpReassembleTest25 (void) { MISSED_START(6); - MISSED_STEP(10, "BB", 2, "\0\0\0BB", 5); - MISSED_STEP(12, "CC", 2, "\0\0\0BBCC", 7); + MISSED_ADD_PAYLOAD(10, "BB", 2); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 3) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 3, "BB", 2) == 1); + MISSED_ADD_PAYLOAD(12, "CC", 2); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 3) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 3, "BBCC", 4) == 1); MISSED_STEP(7, "AAA", 3, "AAABBCC", 7); MISSED_END; + PASS; } /** @@ -2233,7 +2295,10 @@ static int StreamTcpReassembleTest26 (void) { MISSED_START(9); MISSED_STEP(10, "AAA", 3, "AAA", 3); - MISSED_STEP(15, "CC", 2, "AAA\0\0CC", 7); + MISSED_ADD_PAYLOAD(15, "CC", 2); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 0, 0, "AAA", 3) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 1, 3, 2) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 2, 5, "CC", 2) == 1); MISSED_STEP(13, "BB", 2, "AAABBCC", 7); MISSED_END; } @@ -2265,10 +2330,16 @@ static int StreamTcpReassembleTest27 (void) static int StreamTcpReassembleTest28 (void) { MISSED_START(6); - MISSED_STEP(10, "AAA", 3, "\0\0\0AAA", 6); - MISSED_STEP(13, "BB", 2, "\0\0\0AAABB", 8); + MISSED_ADD_PAYLOAD(10, "AAA", 3); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 3) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 3, "AAA", 3) == 1); + MISSED_ADD_PAYLOAD(13, "BB", 2); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 3) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 3, "AAABB", 5) == 1); ssn.state = TCP_TIME_WAIT; - MISSED_STEP(15, "CC", 2, "\0\0\0AAABBCC", 10); + MISSED_ADD_PAYLOAD(15, "CC", 2); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 3) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 3, "AAABBCC", 7) == 1); MISSED_END; } @@ -2285,7 +2356,10 @@ static int StreamTcpReassembleTest29 (void) MISSED_START(9); MISSED_STEP(10, "AAA", 3, "AAA", 3); ssn.state = TCP_TIME_WAIT; - MISSED_STEP(15, "CC", 2, "AAA\0\0CC", 7); + MISSED_ADD_PAYLOAD(15, "CC", 2); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 0, 0, "AAA", 3) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 1, 3, 2) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 2, 5, "CC", 2) == 1); MISSED_END; } diff --git a/src/tests/stream-tcp-inline.c b/src/tests/stream-tcp-inline.c index 469889e956..3da4d44bf3 100644 --- a/src/tests/stream-tcp-inline.c +++ b/src/tests/stream-tcp-inline.c @@ -59,16 +59,24 @@ static int VALIDATE(TcpStream *stream, uint8_t *data, uint32_t data_len) StreamTcpUTDeinit(ra_ctx); \ PASS -#define INLINE_STEP(rseq, seg, seglen, buf, buflen, packet, packetlen) \ - p = UTHBuildPacketReal((uint8_t *)(seg), (seglen), IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); \ - FAIL_IF(p == NULL); \ - p->tcph->th_seq = htonl(stream->isn + (rseq)); \ - p->tcph->th_ack = htonl(31); \ - FAIL_IF (StreamTcpReassembleHandleSegmentHandleData(&tv, ra_ctx, &ssn, stream, p) < 0); \ - FAIL_IF (memcmp(p->payload, packet, MIN((packetlen),p->payload_len)) != 0); \ - UTHFreePacket(p); \ +#define INLINE_ADD_PAYLOAD(rseq, seg, seglen, packet, packetlen) \ + p = UTHBuildPacketReal( \ + (uint8_t *)(seg), (seglen), IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); \ + FAIL_IF(p == NULL); \ + p->tcph->th_seq = htonl(stream->isn + (rseq)); \ + p->tcph->th_ack = htonl(31); \ + FAIL_IF(StreamTcpReassembleHandleSegmentHandleData(&tv, ra_ctx, &ssn, stream, p) < 0); \ + FAIL_IF(memcmp(p->payload, packet, MIN((packetlen), p->payload_len)) != 0); \ + UTHFreePacket(p); + +#define INLINE_STEP(rseq, seg, seglen, buf, buflen, packet, packetlen) \ + INLINE_ADD_PAYLOAD((rseq), (seg), (seglen), (packet), (packetlen)); \ FAIL_IF(!(VALIDATE(stream, (uint8_t *)(buf), (buflen)))); +int UTHCheckGapAtPostion(TcpStream *stream, int pos, uint64_t offset, uint32_t len); +int UTHCheckDataAtPostion( + TcpStream *stream, int pos, uint64_t offset, const char *data, uint32_t len); + /** \test full overlap */ static int StreamTcpInlineTest01(void) { @@ -100,7 +108,9 @@ static int StreamTcpInlineTest03(void) static int StreamTcpInlineTest04(void) { INLINE_START(0); - INLINE_STEP(3, "ABCDE", 5, "\0\0ABCDE", 7, "ABCDE", 5); + INLINE_ADD_PAYLOAD(3, "ABCDE", 5, "ABCDE", 5); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 2) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 2, "ABCDE", 5) == 1); INLINE_STEP(1, "xxxxx", 5, "xxABCDE", 7, "xxABC", 5); INLINE_END; } @@ -109,8 +119,13 @@ static int StreamTcpInlineTest04(void) static int StreamTcpInlineTest05(void) { INLINE_START(0); - INLINE_STEP(8, "ABCDE", 5, "\0\0\0\0\0\0\0ABCDE", 12, "ABCDE", 5); - INLINE_STEP(1, "xxxxx", 5, "xxxxx\0\0ABCDE", 12, "xxxxx", 5); + INLINE_ADD_PAYLOAD(8, "ABCDE", 5, "ABCDE", 5); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 7) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 7, "ABCDE", 5) == 1); + INLINE_ADD_PAYLOAD(1, "xxxxx", 5, "xxxxx", 5); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 0, 0, "xxxxx", 5) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 1, 5, 2) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 2, 7, "ABCDE", 5) == 1); INLINE_END; } @@ -118,10 +133,30 @@ static int StreamTcpInlineTest05(void) static int StreamTcpInlineTest06(void) { INLINE_START(0); - INLINE_STEP(2, "A", 1, "\0A", 2, "A", 1); - INLINE_STEP(4, "A", 1, "\0A\0A", 4, "A", 1); - INLINE_STEP(6, "A", 1, "\0A\0A\0A", 6, "A", 1); - INLINE_STEP(8, "A", 1, "\0A\0A\0A\0A", 8, "A", 1); + INLINE_ADD_PAYLOAD(2, "A", 1, "A", 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 1, "A", 1) == 1); + INLINE_ADD_PAYLOAD(4, "A", 1, "A", 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 1, "A", 1) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 2, 2, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 3, 3, "A", 1) == 1); + INLINE_ADD_PAYLOAD(6, "A", 1, "A", 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 1, "A", 1) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 2, 2, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 3, 3, "A", 1) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 4, 4, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 5, 5, "A", 1) == 1); + INLINE_ADD_PAYLOAD(8, "A", 1, "A", 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 1, "A", 1) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 2, 2, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 3, 3, "A", 1) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 4, 4, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 5, 5, "A", 1) == 1); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 6, 6, 1) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 7, 7, "A", 1) == 1); INLINE_STEP(1, "xxxxxxxxx", 9, "xAxAxAxAx", 9, "xAxAxAxAx", 9); INLINE_END; } @@ -130,7 +165,9 @@ static int StreamTcpInlineTest06(void) static int StreamTcpInlineTest07(void) { INLINE_START(0); - INLINE_STEP(3, "ABCDE", 5, "\0\0ABCDE", 7, "ABCDE", 5); + INLINE_ADD_PAYLOAD(3, "ABCDE", 5, "ABCDE", 5); + FAIL_IF_NOT(UTHCheckGapAtPostion(stream, 0, 0, 2) == 1); + FAIL_IF_NOT(UTHCheckDataAtPostion(stream, 1, 2, "ABCDE", 5) == 1); INLINE_STEP(1, "XXABC", 5, "XXABCDE", 7, "XXABC", 5); INLINE_END; } -- 2.47.2