From: Philippe Antoine Date: Thu, 17 Dec 2020 10:52:42 +0000 (+0100) Subject: http: introduces ALPROTO_HTTP_ANY X-Git-Tag: suricata-7.0.0-beta1~1793 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93e6401ce05789f77533667d37eab28a62616a3c;p=thirdparty%2Fsuricata.git http: introduces ALPROTO_HTTP_ANY For any versions of HTTP, both ALPROTO_HTTP and ALPROTO_HTTP2 --- diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index c85e864595..2d3826b8bd 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -2094,9 +2094,15 @@ void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos) { SCEnter(); - AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos); - AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos); - AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos); + // Custom case for only signature-only protocol so far + if (alproto == ALPROTO_HTTP_ANY) { + AppLayerProtoDetectSupportedIpprotos(ALPROTO_HTTP, ipprotos); + AppLayerProtoDetectSupportedIpprotos(ALPROTO_HTTP2, ipprotos); + } else { + AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos); + AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos); + AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos); + } SCReturn; } @@ -2109,6 +2115,7 @@ AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name) AppProto b = StringToAppProto(alproto_name); for (a = 0; a < ALPROTO_MAX; a++) { if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) { + // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled SCReturnCT(b, "AppProto"); } } diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index a80ac9484e..4a5c03abe8 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1140,6 +1140,11 @@ uint64_t AppLayerParserGetTransactionActive(const Flow *f, int AppLayerParserSupportsFiles(uint8_t ipproto, AppProto alproto) { + // Custom case for only signature-only protocol so far + if (alproto == ALPROTO_HTTP_ANY) { + return AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP) || + AppLayerParserSupportsFiles(ipproto, ALPROTO_HTTP2); + } if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles != NULL) return TRUE; return FALSE; diff --git a/src/app-layer-protos.c b/src/app-layer-protos.c index ecb00684ae..de8f0dd270 100644 --- a/src/app-layer-protos.c +++ b/src/app-layer-protos.c @@ -120,6 +120,9 @@ const char *AppProtoToString(AppProto alproto) case ALPROTO_HTTP2: proto_name = "http2"; break; + case ALPROTO_HTTP_ANY: + proto_name = "http_any"; + break; case ALPROTO_FAILED: proto_name = "failed"; break; @@ -138,7 +141,10 @@ AppProto StringToAppProto(const char *proto_name) { if (proto_name == NULL) return ALPROTO_UNKNOWN; - if (strcmp(proto_name,"http")==0) return ALPROTO_HTTP; + if (strcmp(proto_name, "http") == 0) + return ALPROTO_HTTP_ANY; + if (strcmp(proto_name, "http1") == 0) + return ALPROTO_HTTP; if (strcmp(proto_name,"ftp")==0) return ALPROTO_FTP; if (strcmp(proto_name, "ftp-data") == 0) return ALPROTO_FTPDATA; diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 77a37b7bf2..f5f41959fe 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -58,6 +58,10 @@ enum AppProtoEnum { ALPROTO_RDP, ALPROTO_HTTP2, + // signature-only (ie not seen in flow) + // HTTP for any version (ALPROTO_HTTP (version 1) or ALPROTO_HTTP2) + ALPROTO_HTTP_ANY, + /* used by the probing parser when alproto detection fails * permanently for that particular stream */ ALPROTO_FAILED, @@ -80,6 +84,11 @@ static inline bool AppProtoIsValid(AppProto a) // wether a signature AppProto matches a flow (or signature) AppProto static inline bool AppProtoEquals(AppProto sigproto, AppProto alproto) { + switch (sigproto) { + case ALPROTO_HTTP_ANY: + return (alproto == ALPROTO_HTTP) || (alproto == ALPROTO_HTTP2) || + (alproto == ALPROTO_HTTP_ANY); + } return (sigproto == alproto); } diff --git a/src/detect-app-layer-event.c b/src/detect-app-layer-event.c index 2a2bf28296..3644978033 100644 --- a/src/detect-app-layer-event.c +++ b/src/detect-app-layer-event.c @@ -236,6 +236,16 @@ static int DetectAppLayerEventParseAppP2(DetectAppLayerEventData *data, return 0; } +static AppProto AppLayerEventGetProtoByName(char *alproto_name) +{ + AppProto alproto = AppLayerGetProtoByName(alproto_name); + if (alproto == ALPROTO_HTTP_ANY) { + // app-layer events http refer to http1 + alproto = ALPROTO_HTTP; + } + return alproto; +} + static DetectAppLayerEventData *DetectAppLayerEventParseAppP1(const char *arg) { /* period index */ @@ -250,7 +260,7 @@ static DetectAppLayerEventData *DetectAppLayerEventParseAppP1(const char *arg) /* + 1 for trailing \0 */ strlcpy(alproto_name, arg, p_idx - arg + 1); - const AppProto alproto = AppLayerGetProtoByName(alproto_name); + const AppProto alproto = AppLayerEventGetProtoByName(alproto_name); if (alproto == ALPROTO_UNKNOWN) { if (!strcmp(alproto_name, "file")) { needs_detctx = true; diff --git a/src/detect-app-layer-protocol.c b/src/detect-app-layer-protocol.c index 569d35253b..3dc4e55219 100644 --- a/src/detect-app-layer-protocol.c +++ b/src/detect-app-layer-protocol.c @@ -290,7 +290,7 @@ static int DetectAppLayerProtocolTest01(void) { DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", false); FAIL_IF_NULL(data); - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated != 0); DetectAppLayerProtocolFree(NULL, data); PASS; @@ -300,7 +300,7 @@ static int DetectAppLayerProtocolTest02(void) { DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", true); FAIL_IF_NULL(data); - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated == 0); DetectAppLayerProtocolFree(NULL, data); PASS; @@ -324,7 +324,7 @@ static int DetectAppLayerProtocolTest03(void) FAIL_IF_NULL(s->sm_lists[DETECT_SM_LIST_MATCH]->ctx); data = (DetectAppLayerProtocolData *)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx; - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated); DetectEngineCtxFree(de_ctx); PASS; @@ -349,7 +349,7 @@ static int DetectAppLayerProtocolTest04(void) data = (DetectAppLayerProtocolData*)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx; FAIL_IF_NULL(data); - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated == 0); DetectEngineCtxFree(de_ctx); @@ -375,7 +375,7 @@ static int DetectAppLayerProtocolTest05(void) data = (DetectAppLayerProtocolData*)s->sm_lists[DETECT_SM_LIST_MATCH]->ctx; FAIL_IF_NULL(data); - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated == 0); data = (DetectAppLayerProtocolData*)s->sm_lists[DETECT_SM_LIST_MATCH]->next->ctx; @@ -515,7 +515,7 @@ static int DetectAppLayerProtocolTest14(void) FAIL_IF_NULL(s1->sm_lists[DETECT_SM_LIST_MATCH]); FAIL_IF_NULL(s1->sm_lists[DETECT_SM_LIST_MATCH]->ctx); data = (DetectAppLayerProtocolData *)s1->sm_lists[DETECT_SM_LIST_MATCH]->ctx; - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated); Signature *s2 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " @@ -525,7 +525,7 @@ static int DetectAppLayerProtocolTest14(void) FAIL_IF_NULL(s2->sm_lists[DETECT_SM_LIST_MATCH]); FAIL_IF_NULL(s2->sm_lists[DETECT_SM_LIST_MATCH]->ctx); data = (DetectAppLayerProtocolData *)s2->sm_lists[DETECT_SM_LIST_MATCH]->ctx; - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated); /* flow:established and other options not supported for PD-only */ @@ -536,7 +536,7 @@ static int DetectAppLayerProtocolTest14(void) FAIL_IF_NULL(s3->sm_lists[DETECT_SM_LIST_MATCH]); FAIL_IF_NULL(s3->sm_lists[DETECT_SM_LIST_MATCH]->ctx); data = (DetectAppLayerProtocolData *)s3->sm_lists[DETECT_SM_LIST_MATCH]->ctx; - FAIL_IF(data->alproto != ALPROTO_HTTP); + FAIL_IF(data->alproto != ALPROTO_HTTP_ANY); FAIL_IF(data->negated); SigGroupBuild(de_ctx); diff --git a/src/detect-file-data.c b/src/detect-file-data.c index 78e6bcb9f4..d38e8eec81 100644 --- a/src/detect-file-data.c +++ b/src/detect-file-data.c @@ -269,13 +269,14 @@ static int DetectFiledataSetup (DetectEngineCtx *de_ctx, Signature *s, const cha (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_HTTP && s->alproto != ALPROTO_SMTP && s->alproto != ALPROTO_SMB && s->alproto != ALPROTO_HTTP2 && s->alproto != ALPROTO_FTP && - s->alproto != ALPROTO_FTPDATA)) { + s->alproto != ALPROTO_FTPDATA && s->alproto != ALPROTO_HTTP_ANY)) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); return -1; } - if (s->alproto == ALPROTO_HTTP && (s->init_data->init_flags & SIG_FLAG_INIT_FLOW) && - (s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_TOCLIENT)) { + if ((s->alproto == ALPROTO_HTTP || s->alproto == ALPROTO_HTTP_ANY) && + (s->init_data->init_flags & SIG_FLAG_INIT_FLOW) && (s->flags & SIG_FLAG_TOSERVER) && + !(s->flags & SIG_FLAG_TOCLIENT)) { SCLogError(SC_ERR_INVALID_SIGNATURE, "Can't use file_data with " "flow:to_server or flow:from_client with http."); return -1; @@ -299,11 +300,11 @@ static int DetectFiledataSetup (DetectEngineCtx *de_ctx, Signature *s, const cha static void DetectFiledataSetupCallback(const DetectEngineCtx *de_ctx, Signature *s) { - if (s->alproto == ALPROTO_HTTP || s->alproto == ALPROTO_UNKNOWN) { + if (s->alproto == ALPROTO_HTTP || s->alproto == ALPROTO_UNKNOWN || + s->alproto == ALPROTO_HTTP_ANY) { AppLayerHtpEnableResponseBodyCallback(); } - /* server body needs to be inspected in sync with stream if possible */ s->init_data->init_flags |= SIG_FLAG_INIT_NEED_FLUSH; diff --git a/src/detect-filestore.c b/src/detect-filestore.c index b35565cd45..cf995a6920 100644 --- a/src/detect-filestore.c +++ b/src/detect-filestore.c @@ -455,7 +455,7 @@ static int DetectFilestoreSetup (DetectEngineCtx *de_ctx, Signature *s, const ch sm->ctx = (SigMatchCtx*)NULL; } - if (s->alproto == ALPROTO_HTTP) { + if (s->alproto == ALPROTO_HTTP || s->alproto == ALPROTO_HTTP_ANY) { AppLayerHtpNeedFileInspection(); } diff --git a/src/detect-parse.c b/src/detect-parse.c index 2fe943ae04..85c72b4490 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1493,6 +1493,8 @@ int DetectSignatureSetAppProto(Signature *s, AppProto alproto) if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, alproto)) { if (AppProtoEquals(alproto, s->alproto)) { + // happens if alproto = HTTP_ANY and s->alproto = HTTP1 + // in this case, we must keep the most restrictive HTTP1 alproto = s->alproto; } else { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, @@ -1874,7 +1876,7 @@ static int SigValidate(DetectEngineCtx *de_ctx, Signature *s) SCReturnInt(0); } - if (s->alproto == ALPROTO_HTTP) { + if (s->alproto == ALPROTO_HTTP || s->alproto == ALPROTO_HTTP_ANY) { AppLayerHtpNeedFileInspection(); } }