]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
applayer: on protocol change, use previous state
authorPhilippe Antoine <contact@catenacyber.fr>
Wed, 9 Sep 2020 08:09:33 +0000 (10:09 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 9 Sep 2020 14:22:11 +0000 (16:22 +0200)
src/app-layer-detect-proto.c
src/app-layer-parser.c
src/app-layer-parser.h
src/app-layer.c

index 696a97af306d2a617f085f7fb3dd70d18b40d65f..d45fccf27879b44b840fcf26b82cb925b618e443 100644 (file)
@@ -1868,7 +1868,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);
@@ -1878,8 +1877,8 @@ void AppLayerProtoDetectReset(Flow *f)
     f->probing_parser_toserver_alproto_masks = 0;
     f->probing_parser_toclient_alproto_masks = 0;
 
-    AppLayerParserStateCleanup(f, f->alstate, f->alparser);
-    f->alstate = NULL;
+    // Does not free the structures for the parser
+    // keeps f->alstate for new state creation
     f->alparser = NULL;
     f->alproto    = ALPROTO_UNKNOWN;
     f->alproto_ts = ALPROTO_UNKNOWN;
index f3b92c16757fc29dfb67851b4a7b247b87c4b855..d22a046977a17b364258ceb197c1df5d23021b1e 100644 (file)
@@ -1214,7 +1214,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow
     SetEOFFlags(pstate, flags);
 
     alstate = f->alstate;
-    if (alstate == NULL) {
+    if (alstate == NULL || FlowChangeProto(f)) {
         f->alstate = alstate = p->StateAlloc(alstate, f->alproto_orig);
         if (alstate == NULL)
             goto error;
@@ -1449,12 +1449,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);
@@ -1466,6 +1466,11 @@ 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 d662f18665a737c4ccb75166f149010b13ffb9ef..86c3a3696feed77d70e2e38ba4a98f9655186e46 100644 (file)
@@ -257,6 +257,8 @@ int AppLayerParserIsEnabled(AppProto alproto);
 
 /***** 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 a21ba3a80eb0c05d97036c946e8099d81797097b..9ac05c7b1949e1f7f4d36ed2910ef92d7240fae6 100644 (file)
@@ -631,11 +631,17 @@ 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);
         /* 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);
+        FlowUnsetChangeProtoFlag(f);
+        AppLayerParserStateProtoCleanup(f->protomap, f->alproto_orig, alstate_orig, alparser);
+        if (rd != 0) {
             SCLogDebug("proto detect failure");
+            f->alstate = NULL;
             goto failure;
         }
         SCLogDebug("protocol change, old %s, new %s",