]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
applayer: keep running detection on protocol change 5448/head
authorPhilippe Antoine <contact@catenacyber.fr>
Wed, 9 Sep 2020 08:09:33 +0000 (10:09 +0200)
committerShivani Bhardwaj <shivanib134@gmail.com>
Sat, 26 Sep 2020 18:52:26 +0000 (00:22 +0530)
ie do not stop on first try if we do not have enough data

(cherry picked from commit 07cbdb32b3f6e63e2d08b29e6db0c0ac3d819a70)

src/app-layer-detect-proto.c
src/app-layer-parser.c
src/app-layer-parser.h
src/app-layer.c

index 9add685f69fc6287a7cbb474513cd9be87b0d49c..ef4161bd6238b8f24d1518f945fad5678332202b 100644 (file)
@@ -1720,7 +1720,6 @@ void AppLayerRequestProtocolTLSUpgrade(Flow *f)
 
 void AppLayerProtoDetectReset(Flow *f)
 {
-    FlowUnsetChangeProtoFlag(f);
     FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
     FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
     FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
@@ -1730,7 +1729,7 @@ void AppLayerProtoDetectReset(Flow *f)
     f->probing_parser_toserver_alproto_masks = 0;
     f->probing_parser_toclient_alproto_masks = 0;
 
-    AppLayerParserStateCleanup(f, f->alstate, f->alparser);
+    // Does not free the structures for the parser
     f->alstate = NULL;
     f->alparser = NULL;
     f->alproto    = ALPROTO_UNKNOWN;
index ed9f419d6b149be8d1ac6ffbe6d23c4dd5df745c..e132d795e4652cdacb99d518e6793db3befbc9e9 100644 (file)
@@ -1411,12 +1411,12 @@ void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *s
 
 /***** Cleanup *****/
 
-void AppLayerParserStateCleanup(const Flow *f, void *alstate,
-                                AppLayerParserState *pstate)
+void AppLayerParserStateProtoCleanup(
+        uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate)
 {
     SCEnter();
 
-    AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[f->protomap][f->alproto];
+    AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[protomap][alproto];
 
     if (ctx->StateFree != NULL && alstate != NULL)
         ctx->StateFree(alstate);
@@ -1428,6 +1428,12 @@ void AppLayerParserStateCleanup(const Flow *f, void *alstate,
     SCReturn;
 }
 
+void AppLayerParserStateCleanup(const Flow *f, void *alstate,
+                                AppLayerParserState *pstate)
+{
+    AppLayerParserStateProtoCleanup(f->protomap, f->alproto, alstate, pstate);
+}
+
 static void ValidateParserProtoDump(AppProto alproto, uint8_t ipproto)
 {
     uint8_t map = FlowGetProtoMapping(ipproto);
index b57315039963626f6b0e45d79c063a03e72fb25c..a5d3d54beecc5ccc100aa6b3890decc6c500f8a3 100644 (file)
@@ -244,6 +244,8 @@ void AppLayerParserSetStreamDepthFlag(uint8_t ipproto, AppProto alproto, void *s
 
 /***** Cleanup *****/
 
+void AppLayerParserStateProtoCleanup(
+        uint8_t protomap, AppProto alproto, void *alstate, AppLayerParserState *pstate);
 void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate);
 
 void AppLayerParserRegisterProtocolParsers(void);
index 98bba4a3c9ee0da9a63bf9d0bc9268932e2a451b..2fd88b16011c8d7413eb1564c51953768d450306 100644 (file)
@@ -594,10 +594,26 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
     } else if (alproto != ALPROTO_UNKNOWN && FlowChangeProto(f)) {
         f->alproto_orig = f->alproto;
         SCLogDebug("protocol change, old %s", AppProtoToString(f->alproto_orig));
+        void *alstate_orig = f->alstate;
+        AppLayerParserState *alparser = f->alparser;
+        // we delay AppLayerParserStateCleanup because we may need previous parser state
         AppLayerProtoDetectReset(f);
+        StreamTcpResetStreamFlagAppProtoDetectionCompleted(&ssn->client);
+        StreamTcpResetStreamFlagAppProtoDetectionCompleted(&ssn->server);
         /* rerun protocol detection */
-        if (TCPProtoDetect(tv, ra_ctx, app_tctx, p, f, ssn, stream,
-                           data, data_len, flags) != 0) {
+        int rd = TCPProtoDetect(tv, ra_ctx, app_tctx, p, f, ssn, stream, data, data_len, flags);
+        if (f->alproto == ALPROTO_UNKNOWN) {
+            // not enough data, revert AppLayerProtoDetectReset to rerun detection
+            f->alparser = alparser;
+            f->alstate = alstate_orig;
+            f->alproto = f->alproto_orig;
+            f->alproto_tc = f->alproto_orig;
+            f->alproto_ts = f->alproto_orig;
+        } else {
+            FlowUnsetChangeProtoFlag(f);
+            AppLayerParserStateProtoCleanup(f->protomap, f->alproto_orig, alstate_orig, alparser);
+        }
+        if (rd != 0) {
             SCLogDebug("proto detect failure");
             goto failure;
         }