]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http: introduces ALPROTO_HTTP_ANY
authorPhilippe Antoine <contact@catenacyber.fr>
Thu, 17 Dec 2020 10:52:42 +0000 (11:52 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 18 Feb 2021 11:22:55 +0000 (12:22 +0100)
For any versions of HTTP, both ALPROTO_HTTP and ALPROTO_HTTP2

src/app-layer-detect-proto.c
src/app-layer-parser.c
src/app-layer-protos.c
src/app-layer-protos.h
src/detect-app-layer-event.c
src/detect-app-layer-protocol.c
src/detect-file-data.c
src/detect-filestore.c
src/detect-parse.c

index c85e86459599cf25d9954f1a1908f1eaecec0fde..2d3826b8bde216ae98d35644034018f46f76b1a5 100644 (file)
@@ -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");
         }
     }
index a80ac9484e9f088f7ce1b8ac28339665d2cd9ee7..4a5c03abe8d415402cfd842d135bff67aad52b83 100644 (file)
@@ -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;
index ecb00684ae1dd9b5a4bed1840c9748e7b66f7ce9..de8f0dd270bb2390fe06e246670ef75bf5f19a8a 100644 (file)
@@ -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;
index 77a37b7bf2d7e96f4dec8b998c8060bbeef26293..f5f41959feaec7f6a5dd34ac929d11df72fa179d 100644 (file)
@@ -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);
 }
 
index 2a2bf28296bad7fa1d0e8573ba7ad20091aef58a..364497803378501ede6af71905048f23a8f553ea 100644 (file)
@@ -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;
index 569d35253bd33065a7f9c20e7e8aa8597258975b..3dc4e55219c27ce37d0f475836a2270f38803b66 100644 (file)
@@ -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);
index 78e6bcb9f4d090cec12c3e0ccc48165794899e34..d38e8eec81f74df5fb1c1403db688604271aae93 100644 (file)
@@ -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;
 
index b35565cd45585598fa4e8fdaf47195db2a05d363..cf995a692082d5bedc264b0a5bc485017b826f39 100644 (file)
@@ -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();
     }
 
index 2fe943ae0407ec45c8a33128751889a8eb3006b5..85c72b449020d0db635f4fcdcfa9638ffc4bd3ec 100644 (file)
@@ -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();
         }
     }