From a54f52278b351ae445fed03502a8f68a1518ef92 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 16 Oct 2014 18:38:19 +0200 Subject: [PATCH] stream: fix 'bad window update' false positive ACK packets completing a valid FIN shutdown could be flagged as 'bad window update' if they would shrink the window. This patch detects this case before doing the bad window update check. --- src/stream-tcp.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 86f995ccd9..d4ea8d9091 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -4239,6 +4239,45 @@ static int StreamTcpPacketIsWindowUpdate(TcpSession *ssn, Packet *p) return 0; } +/** + * Try to detect whether a packet is a valid FIN 4whs final ack. + * + */ +static int StreamTcpPacketIsFinShutdownAck(TcpSession *ssn, Packet *p) +{ + TcpStream *stream = NULL, *ostream = NULL; + uint32_t seq; + uint32_t ack; + + if (p->flags & PKT_PSEUDO_STREAM_END) + return 0; + if (ssn->state != TCP_TIME_WAIT) + return 0; + if (p->tcph->th_flags != TH_ACK) + return 0; + if (p->payload_len != 0) + return 0; + + if (PKT_IS_TOSERVER(p)) { + stream = &ssn->client; + ostream = &ssn->server; + } else { + stream = &ssn->server; + ostream = &ssn->client; + } + + seq = TCP_GET_SEQ(p); + ack = TCP_GET_ACK(p); + + SCLogDebug("%"PRIu64", seq %u ack %u stream->next_seq %u ostream->next_seq %u", + p->pcap_cnt, seq, ack, stream->next_seq, ostream->next_seq); + + if (SEQ_EQ(stream->next_seq + 1, seq) && SEQ_EQ(ack, ostream->next_seq + 1)) { + return 1; + } + return 0; +} + /** * Try to detect packets doing bad window updates * @@ -4383,9 +4422,10 @@ int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, /* if packet is not a valid window update, check if it is perhaps * a bad window update that we should ignore (and alert on) */ - if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) - if (StreamTcpPacketIsBadWindowUpdate(ssn,p)) - goto skip; + if (StreamTcpPacketIsFinShutdownAck(ssn, p) == 0) + if (StreamTcpPacketIsWindowUpdate(ssn, p) == 0) + if (StreamTcpPacketIsBadWindowUpdate(ssn,p)) + goto skip; switch (ssn->state) { case TCP_SYN_SENT: -- 2.47.2