]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
applayer: keep running detection on protocol change 5440/head
authorPhilippe Antoine <contact@catenacyber.fr>
Wed, 9 Sep 2020 08:09:33 +0000 (10:09 +0200)
committerJeff Lucovsky <jeff@lucovsky.org>
Wed, 23 Sep 2020 12:45:23 +0000 (08:45 -0400)
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 7d6f9854b1f6944556060dfa2d21bb0f8517d02e..be5607e70d394a2c864a30b610047d88c23d624a 100644 (file)
@@ -1867,7 +1867,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);
@@ -1877,7 +1876,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 660289e66d3acfca9b85bf654608d245e7ed4c79..133a9139e83b4f4578c4ce572531d965a404d161 100644 (file)
@@ -1417,12 +1417,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);
@@ -1434,6 +1434,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 0ce16c08985f7226bbeaaa04aad944d6ecec975b..16efc7911dfc24d6318a08b03a2012bc5dc157e9 100644 (file)
@@ -246,6 +246,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 a80f67137419a5d62ae33950b35629591ab8c25b..7e52237cd53c4b9164dabbc53cd50ca2b6e78212 100644 (file)
@@ -625,10 +625,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;
         }