]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
stream: implement raw reassembly stop api
authorVictor Julien <victor@inliniac.net>
Thu, 24 Apr 2014 08:48:37 +0000 (10:48 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 2 May 2014 09:55:12 +0000 (11:55 +0200)
Implement StreamTcpSetDisableRawReassemblyFlag() which stops raw
reassembly for _NEW_ segments in a stream direction.

It is used only by TLS/SSL now, to flag the streams as encrypted.
Existing segments will still be reassembled and inspected, while
new segments won't be. This allows for pattern based inspection
of the TLS handshake.

Like is the case with completely disabled 'raw' reassembly, the
logic is that the segments are flagged as completed for 'raw' right
away. So they are not considered in raw reassembly anymore.

As no new segments will be considered, the chunk limit check will
return true on the next call.

src/app-layer-parser.c
src/stream-tcp-private.h
src/stream-tcp-reassemble.c
src/stream-tcp-reassemble.h
src/stream-tcp.c

index 24c22d9a75545332ffd0def45418535c95dab1e2..75bfc9f477314807cde304fc97995a484f27f134 100644 (file)
@@ -850,9 +850,18 @@ int AppLayerParserParse(AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alp
     }
 
     /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */
-    if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) {
+    if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) {
         FlowSetNoPayloadInspectionFlag(f);
-        AppLayerParserTriggerRawStreamReassembly(f);
+        /* Set the no reassembly flag for both the stream in this TcpSession */
+        if (f->proto == IPPROTO_TCP) {
+            /* Used only if it's TCP */
+            TcpSession *ssn = f->protoctx;
+            if (ssn != NULL) {
+                StreamTcpSetDisableRawReassemblyFlag(ssn, 0);
+                StreamTcpSetDisableRawReassemblyFlag(ssn, 1);
+                AppLayerParserTriggerRawStreamReassembly(f);
+            }
+        }
     }
 
     /* next, see if we can get rid of transactions now */
index 7f576396c1d5fe584a85c7f75434f417aff6e1ea..e8635c875074eb098338d7ff5681edd03b6f05c4 100644 (file)
@@ -165,6 +165,8 @@ enum
 #define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED 0x0080
 /** App proto detection skipped */
 #define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED 0x0100
+/** Raw reassembly disabled for new segments */
+#define STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED 0x0200
 
 /*
  * Per SEGMENT flags
index 53a740ffe146fbf74d92be5bed05a32f0611476c..7dc7b7696a24c6da2991f8fc7ce20a7cd8ddbf01 100644 (file)
@@ -1882,6 +1882,14 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre
     seg->payload_len = size;
     seg->seq = TCP_GET_SEQ(p);
 
+    /* if raw reassembly is disabled for new segments, flag each
+     * segment as complete for raw before insert */
+    if (stream->flags & STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED) {
+        seg->flags |= SEGMENTTCP_FLAG_RAW_PROCESSED;
+        SCLogDebug("segment %p flagged with SEGMENTTCP_FLAG_RAW_PROCESSED, "
+                   "flags %02x", seg, seg->flags);
+    }
+
     /* proto detection skipped, but now we do get data. Set event. */
     if (stream->seg_list == NULL &&
         stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED) {
@@ -1965,6 +1973,12 @@ static int StreamTcpReassembleRawCheckLimit(TcpSession *ssn, TcpStream *stream,
         SCReturnInt(1);
     }
 
+    if (stream->flags & STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED) {
+        SCLogDebug("reassembling now as STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED is set, "
+                "so no new segments will be considered");
+        SCReturnInt(1);
+    }
+
     /* some states mean we reassemble no matter how much data we have */
     if (ssn->state >= TCP_TIME_WAIT)
         SCReturnInt(1);
@@ -2725,10 +2739,8 @@ static inline int StreamTcpReturnSegmentCheck(const Flow *f, TcpSession *ssn, Tc
     }
 
     /* check raw reassembly conditions */
-    if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION)) {
-        if (!(seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) {
-            SCReturnInt(0);
-        }
+    if (!(seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) {
+        SCReturnInt(0);
     }
 
     SCReturnInt(1);
@@ -2935,6 +2947,10 @@ int StreamTcpReassembleAppLayer (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
             StreamTcpSegmentReturntoPool(seg);
             seg = next_seg;
             continue;
+        } else if (StreamTcpAppLayerSegmentProcessed(stream, seg)) {
+            TcpSegment *next_seg = seg->next;
+            seg = next_seg;
+            continue;
         }
 
         /* we've run into a sequence gap */
@@ -3235,11 +3251,6 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
                 seg, seg->seq, seg->payload_len,
                 (uint32_t)(seg->seq + seg->payload_len), seg->flags);
 
-        if (p->flow->flags & FLOW_NOPAYLOAD_INSPECTION) {
-            SCLogDebug("FLOW_NOPAYLOAD_INSPECTION set, breaking out");
-            break;
-        }
-
         if (StreamTcpReturnSegmentCheck(p->flow, ssn, stream, seg) == 1) {
             SCLogDebug("removing segment");
             TcpSegment *next_seg = seg->next;
@@ -3247,6 +3258,10 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
             StreamTcpSegmentReturntoPool(seg);
             seg = next_seg;
             continue;
+        } else if(seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED) {
+            TcpSegment *next_seg = seg->next;
+            seg = next_seg;
+            continue;
         }
 
         /* we've run into a sequence gap */
index dd2dc6574a817ffc48f1a4533df8853deb8881b5..7eca5cf683891d868125aabeca3c3c1ee635d82d 100644 (file)
@@ -87,6 +87,7 @@ int StreamTcpReassembleInlineAppLayer(ThreadVars *tv,
 void StreamTcpCreateTestPacket(uint8_t *, uint8_t, uint8_t, uint8_t);
 
 void StreamTcpSetSessionNoReassemblyFlag (TcpSession *, char );
+void StreamTcpSetDisableRawReassemblyFlag (TcpSession *ssn, char direction);
 
 void StreamTcpSetOSPolicy(TcpStream *, Packet *);
 void StreamTcpReassemblePause (TcpSession *, char );
index 3fc268c041b8b5aa53a09e6682a0b358b1ce25c7..503415698964209b30cf1ff17c799f72eaacc7fd 100644 (file)
@@ -5223,6 +5223,18 @@ void StreamTcpSetSessionNoReassemblyFlag (TcpSession *ssn, char direction)
                 (ssn->client.flags |= STREAMTCP_STREAM_FLAG_NOREASSEMBLY);
 }
 
+/** \brief  Set the No reassembly flag for the given direction in given TCP
+ *          session.
+ *
+ * \param ssn TCP Session to set the flag in
+ * \param direction direction to set the flag in: 0 toserver, 1 toclient
+ */
+void StreamTcpSetDisableRawReassemblyFlag (TcpSession *ssn, char direction)
+{
+    direction ? (ssn->server.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED) :
+                (ssn->client.flags |= STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED);
+}
+
 #define PSEUDO_PKT_SET_IPV4HDR(nipv4h,ipv4h) do { \
         IPV4_SET_RAW_VER(nipv4h, IPV4_GET_RAW_VER(ipv4h)); \
         IPV4_SET_RAW_HLEN(nipv4h, IPV4_GET_RAW_HLEN(ipv4h)); \