]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer: improve EOF handling
authorVictor Julien <victor@inliniac.net>
Thu, 11 Jun 2015 10:39:53 +0000 (12:39 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 18 Jun 2015 08:18:42 +0000 (10:18 +0200)
On receiving TCP end of stream packets (e.g. RST, but also sometimes FIN
packets), in some cases the AppLayer parser would not be notified. This
could happen in IDS mode, but would especially be an issue in IPS mode.

This patch changes the logic of the AppLayer API to handle this. When no
new data is available, and the stream ends, the AppLayer API now gets
called with a NULL/0 input, but with the EOF flag set.

This allows the AppLayer parser to call it's final routines still in the
context of a real packet.

src/app-layer-htp.c
src/app-layer-parser.c

index c6a6e412beacf0d851118edbe0dce4ccb1e210df..aed1ddeb47835e065f6401de367aa2c85749c772 100644 (file)
@@ -739,28 +739,30 @@ static int HTPHandleRequestData(Flow *f, void *htp_state,
 
     htp_time_t ts = { f->lastts.tv_sec, f->lastts.tv_usec };
     /* pass the new data to the htp parser */
-    r = htp_connp_req_data(hstate->connp, &ts, input, input_len);
+    if (input_len > 0) {
+        r = htp_connp_req_data(hstate->connp, &ts, input, input_len);
 
-    switch(r) {
-        case HTP_STREAM_ERROR:
+        switch(r) {
+            case HTP_STREAM_ERROR:
 
-            hstate->flags |= HTP_FLAG_STATE_ERROR;
-            hstate->flags &= ~HTP_FLAG_STATE_DATA;
-            hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
-            ret = -1;
-            break;
-        case HTP_STREAM_DATA:
-        case HTP_STREAM_DATA_OTHER:
+                hstate->flags |= HTP_FLAG_STATE_ERROR;
+                hstate->flags &= ~HTP_FLAG_STATE_DATA;
+                hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
+                ret = -1;
+                break;
+            case HTP_STREAM_DATA:
+            case HTP_STREAM_DATA_OTHER:
 
-            hstate->flags |= HTP_FLAG_STATE_DATA;
-            break;
-        case HTP_STREAM_TUNNEL:
-            break;
-        default:
-            hstate->flags &= ~HTP_FLAG_STATE_DATA;
-            hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
+                hstate->flags |= HTP_FLAG_STATE_DATA;
+                break;
+            case HTP_STREAM_TUNNEL:
+                break;
+            default:
+                hstate->flags &= ~HTP_FLAG_STATE_DATA;
+                hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
+        }
+        HTPHandleError(hstate);
     }
-    HTPHandleError(hstate);
 
     /* if the TCP connection is closed, then close the HTTP connection */
     if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF) &&
@@ -815,25 +817,27 @@ static int HTPHandleResponseData(Flow *f, void *htp_state,
     hstate->flags &=~ HTP_FLAG_NEW_BODY_SET;
 
     htp_time_t ts = { f->lastts.tv_sec, f->lastts.tv_usec };
-    r = htp_connp_res_data(hstate->connp, &ts, input, input_len);
-    switch(r) {
-        case HTP_STREAM_ERROR:
-            hstate->flags = HTP_FLAG_STATE_ERROR;
-            hstate->flags &= ~HTP_FLAG_STATE_DATA;
-            hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
-            ret = -1;
-            break;
-        case HTP_STREAM_DATA:
-        case HTP_STREAM_DATA_OTHER:
-            hstate->flags |= HTP_FLAG_STATE_DATA;
-            break;
-        case HTP_STREAM_TUNNEL:
-            break;
-        default:
-            hstate->flags &= ~HTP_FLAG_STATE_DATA;
-            hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
-     }
-    HTPHandleError(hstate);
+    if (input_len > 0) {
+        r = htp_connp_res_data(hstate->connp, &ts, input, input_len);
+        switch(r) {
+            case HTP_STREAM_ERROR:
+                hstate->flags = HTP_FLAG_STATE_ERROR;
+                hstate->flags &= ~HTP_FLAG_STATE_DATA;
+                hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
+                ret = -1;
+                break;
+            case HTP_STREAM_DATA:
+            case HTP_STREAM_DATA_OTHER:
+                hstate->flags |= HTP_FLAG_STATE_DATA;
+                break;
+            case HTP_STREAM_TUNNEL:
+                break;
+            default:
+                hstate->flags &= ~HTP_FLAG_STATE_DATA;
+                hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
+        }
+        HTPHandleError(hstate);
+    }
 
     /* if we the TCP connection is closed, then close the HTTP connection */
     if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF) &&
index 655da90213b1d9468b86a24dcc6340216b36321c..2c4d2f8b2c676730f931151b43fffa12fb6b5379 100644 (file)
@@ -890,7 +890,7 @@ int AppLayerParserParse(AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alp
     }
 
     /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
-    if (input_len > 0) {
+    if (input_len > 0 || (flags & STREAM_EOF)) {
         /* invoke the parser */
         if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate,
                 input, input_len,