From 8252416c1013f77a2ee3ffb7703d7fbfdea5d483 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 3 Apr 2014 13:55:22 +0200 Subject: [PATCH] proto-detect: update port logic 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 | 110 +++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 31 deletions(-) diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index 0d7734c4cb..c183e79c0c 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -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 *****/