From: Victor Julien Date: Mon, 30 Jul 2018 08:26:21 +0000 (+0200) Subject: stream: improve TCP CLOSED handling X-Git-Tag: suricata-4.0.6~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=36dacde025267e744517de3e80ea4999b0a2bfe2;p=thirdparty%2Fsuricata.git stream: improve TCP CLOSED handling Trigger app layer reassembly in both directions as soon as we've set the TCP state to closed. In IDS mode, if a toserver packet would close the state, the app layer would not get updated until the next toclient packet. However, in detection, the raw stream inspection would already use all available stream data in detection and move the 'raw stream progress' tracker forward. When in later (a) packet(s) the app layer was updated and inspection ran on the app layer, the stream progress was already moved too far forward. This would lead to signatures that matched on both stream and app layer to not match. By triggering the app layer reassembly as soon as the TCP state is set to closed, the inspection as both the stream and app layer data available at the same time so these rules can match. Bug: #2570 Bug: #2554 --- diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index c478c94cb4..3d757cbce4 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -1699,10 +1699,12 @@ int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ dir = UPDATE_DIR_PACKET; } else if (p->tcph && (p->tcph->th_flags & TH_FIN) && ssn->state > TCP_TIME_WAIT) { dir = UPDATE_DIR_PACKET; + } else if (ssn->state == TCP_CLOSED) { + dir = UPDATE_DIR_BOTH; } /* handle ack received */ - if (dir == UPDATE_DIR_OPPOSING && + if ((dir == UPDATE_DIR_OPPOSING || dir == UPDATE_DIR_BOTH) && StreamTcpReassembleHandleSegmentUpdateACK(tv, ra_ctx, ssn, opposing_stream, p) != 0) { SCLogDebug("StreamTcpReassembleHandleSegmentUpdateACK error"); @@ -1729,7 +1731,7 @@ int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ /* in stream inline mode even if we have no data we call the reassembly * functions to handle EOF */ - if (dir == UPDATE_DIR_PACKET) { + if (dir == UPDATE_DIR_PACKET || dir == UPDATE_DIR_BOTH) { SCLogDebug("inline (%s) or PKT_PSEUDO_STREAM_END (%s)", StreamTcpInlineMode()?"true":"false", (p->flags & PKT_PSEUDO_STREAM_END) ?"true":"false"); diff --git a/src/stream-tcp-reassemble.h b/src/stream-tcp-reassemble.h index 7c5e8bb1d4..dfac4ba152 100644 --- a/src/stream-tcp-reassemble.h +++ b/src/stream-tcp-reassemble.h @@ -54,6 +54,7 @@ enum enum StreamUpdateDir { UPDATE_DIR_PACKET, UPDATE_DIR_OPPOSING, + UPDATE_DIR_BOTH, }; typedef struct TcpReassemblyThreadCtx_ {