]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
proto-detect: update port logic
authorVictor Julien <victor@inliniac.net>
Thu, 3 Apr 2014 11:55:22 +0000 (13:55 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 17 Apr 2014 13:32:25 +0000 (15:32 +0200)
If a flow matches both an 'sp' based PP registration and a 'dp' based,
until now we would only check the 'dp' one. This patch changes that. It
will inspect both.

src/app-layer-detect-proto.c

index 0d7734c4cb83f74360944ba260593262aded7d19..c183e79c0c3d2bc7bf33a8e8eb1f45a1c83e120e 100644 (file)
@@ -319,51 +319,73 @@ static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
                                               uint8_t *buf, uint32_t buflen,
                                               uint8_t ipproto, uint8_t direction)
 {
-    const AppLayerProtoDetectProbingParserPort *pp_port = NULL;
+    const AppLayerProtoDetectProbingParserPort *pp_port_dp = NULL;
+    const AppLayerProtoDetectProbingParserPort *pp_port_sp = NULL;
     const AppLayerProtoDetectProbingParserElement *pe = NULL;
+    const AppLayerProtoDetectProbingParserElement *pe1 = NULL;
+    const AppLayerProtoDetectProbingParserElement *pe2 = NULL;
     AppProto alproto = ALPROTO_UNKNOWN;
     uint32_t *alproto_masks;
+    uint32_t mask = 0;
 
     if (direction & STREAM_TOSERVER) {
         /* first try the destination port */
-        pp_port = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
+        pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
         alproto_masks = &f->probing_parser_toserver_alproto_masks;
-        if (pp_port == NULL) {
+        if (pp_port_dp != NULL) {
+            SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, f->dp);
+
+            /* found based on destination port, so use dp registration */
+            pe1 = pp_port_dp->dp;
+        } else {
             SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16,
                        f->dp);
+        }
 
-            /* dp not found, lets try source port then */
-            pp_port = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->sp);
-            if (pp_port == NULL) {
-                SCLogDebug("toserver - No probing parser registered for source port %"PRIu16,
-                        f->sp);
-                FLOW_SET_PP_DONE(f, direction);
-                goto end;
-            }
+        pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->sp);
+        if (pp_port_sp != NULL) {
+            SCLogDebug("toserver - Probing parser found for source port %"PRIu16, f->sp);
+
+            /* found based on source port, so use sp registration */
+            pe2 = pp_port_sp->sp;
+        } else {
+            SCLogDebug("toserver - No probing parser registered for source port %"PRIu16,
+                    f->sp);
         }
-        pe = pp_port->dp;
     } else {
         /* first try the destination port */
-        pp_port = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
+        pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
         alproto_masks = &f->probing_parser_toclient_alproto_masks;
-        if (pp_port == NULL) {
+        if (pp_port_dp != NULL) {
+            SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, f->dp);
+
+            /* found based on destination port, so use dp registration */
+            pe1 = pp_port_dp->dp;
+        } else {
             SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16,
                        f->dp);
+        }
 
-            /* dp not found, lets try source port then */
-            pp_port = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->sp);
-            if (pp_port == NULL) {
-                SCLogDebug("toclient - No probing parser registered for source port %"PRIu16,
-                        f->sp);
+        pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->sp);
+        if (pp_port_sp != NULL) {
+            SCLogDebug("toclient - Probing parser found for source port %"PRIu16, f->sp);
 
-                FLOW_SET_PP_DONE(f, direction);
-                goto end;
-            }
+            pe2 = pp_port_sp->sp;
+        } else {
+            SCLogDebug("toclient - No probing parser registered for source port %"PRIu16,
+                        f->sp);
         }
-        pe = pp_port->dp;
+    }
+
+    if (pe1 == NULL && pe2 == NULL) {
+        SCLogDebug("%s - No probing parsers found for either port",
+                (direction & STREAM_TOSERVER) ? "toserver":"toclient");
+        FLOW_SET_PP_DONE(f, direction);
+        goto end;
     }
 
     /* run the parser(s) */
+    pe = pe1;
     while (pe != NULL) {
         if ((buflen < pe->min_depth)  ||
             (alproto_masks[0] & pe->alproto_mask)) {
@@ -380,21 +402,47 @@ static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
         }
         pe = pe->next;
     }
+    pe = pe2;
+    while (pe != NULL) {
+        if ((buflen < pe->min_depth)  ||
+            (alproto_masks[0] & pe->alproto_mask)) {
+            pe = pe->next;
+            continue;
+        }
 
-    if (direction & STREAM_TOSERVER) {
-        if (alproto_masks[0] == pp_port->toserver_alproto_mask) {
-            FLOW_SET_PP_DONE(f, direction);
+        alproto = pe->ProbingParser(buf, buflen, NULL);
+        if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED)
             goto end;
+        if (alproto == ALPROTO_FAILED ||
+            (pe->max_depth != 0 && buflen > pe->max_depth)) {
+            alproto_masks[0] |= pe->alproto_mask;
         }
+        pe = pe->next;
+    }
+
+    /* get the mask we need for this direction */
+    if (pp_port_dp && pp_port_sp)
+        mask = pp_port_dp->toserver_alproto_mask|pp_port_sp->toclient_alproto_mask;
+    else if (pp_port_dp)
+        mask = pp_port_dp->toserver_alproto_mask;
+    else if (pp_port_sp)
+        mask = pp_port_sp->toclient_alproto_mask;
+    else
+        mask = 0;
+
+    if (alproto_masks[0] == mask) {
+        FLOW_SET_PP_DONE(f, direction);
+        SCLogDebug("%s, mask is now %08x, needed %08x, so done",
+                (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0], mask);
     } else {
-        if (alproto_masks[0] == pp_port->toclient_alproto_mask) {
-            FLOW_SET_PP_DONE(f, direction);
-            goto end;
-        }
+        SCLogDebug("%s, mask is now %08x, need %08x",
+                (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0], mask);
     }
 
  end:
-    SCReturnCT(alproto, "AppProto");
+    SCLogDebug("%s, mask is now %08x",
+            (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
+    SCReturnUInt(alproto);
 }
 
 /***** Static Internal Calls: PP registration *****/