From: Philippe Antoine Date: Wed, 9 Sep 2020 08:09:33 +0000 (+0200) Subject: applayer: keep running detection on protocol change X-Git-Tag: suricata-5.0.4~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52d2e09effbaced6725c899e258bd7467e3a860f;p=thirdparty%2Fsuricata.git applayer: keep running detection on protocol change ie do not stop on first try if we do not have enough data (cherry picked from commit 07cbdb32b3f6e63e2d08b29e6db0c0ac3d819a70) --- diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index 7d6f9854b1..be5607e70d 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -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; diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 660289e66d..133a9139e8 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -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); diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 0ce16c0898..16efc7911d 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -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); diff --git a/src/app-layer.c b/src/app-layer.c index a80f671374..7e52237cd5 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -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; }