]> 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, 9 Aug 2018 06:15:10 +0000 (08:15 +0200)
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 87f575312ece20a97528d9b1bd0a8afc101c16a2..4174494824c43f0fa03f5e54072cbcecb0d6c782 100644 (file)
@@ -1722,10 +1722,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");
@@ -1770,7 +1772,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 3b03f550c422d28bf36eb4fb02ce15318984cc86..28f1c438e31f611a0a4b481e90727aff4c483fc3 100644 (file)
@@ -54,6 +54,7 @@ enum
 enum StreamUpdateDir {
     UPDATE_DIR_PACKET,
     UPDATE_DIR_OPPOSING,
+    UPDATE_DIR_BOTH,
 };
 
 typedef struct TcpReassemblyThreadCtx_ {