]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
stream: improve TCP CLOSED handling
authorVictor Julien <victor@inliniac.net>
Mon, 30 Jul 2018 08:26:21 +0000 (10:26 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 1 Nov 2018 14:46:10 +0000 (15:46 +0100)
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

src/stream-tcp-reassemble.c
src/stream-tcp-reassemble.h

index c478c94cb4c490c3800016ed0ebea3c7ccc85730..3d757cbce4939e50402b6f2f404c6b2afff28bb9 100644 (file)
@@ -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");
index 7c5e8bb1d44c648af2c69796a13ffff93a59bcf6..dfac4ba15295e76936c35f01d5870278cccc0787 100644 (file)
@@ -54,6 +54,7 @@ enum
 enum StreamUpdateDir {
     UPDATE_DIR_PACKET,
     UPDATE_DIR_OPPOSING,
+    UPDATE_DIR_BOTH,
 };
 
 typedef struct TcpReassemblyThreadCtx_ {