app-layer/probing-parser: implement reverse flow

Implement midstream support for the pure probing parsers. These
need to look up the appropriate parsers based on the reverse
tuple.
pull/3765/head
Victor Julien 6 years ago
parent 34cb49f1e9
commit bb78d48c0a

@ -444,6 +444,39 @@ static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto,
return alproto;
}
static inline AppProto PPGetProto(
const AppLayerProtoDetectProbingParserElement *pe,
Flow *f, uint8_t direction,
uint8_t *buf, uint32_t buflen,
uint32_t *alproto_masks, uint8_t *rdir
)
{
while (pe != NULL) {
if ((buflen < pe->min_depth) ||
(alproto_masks[0] & pe->alproto_mask)) {
pe = pe->next;
continue;
}
AppProto alproto = ALPROTO_UNKNOWN;
if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
alproto = pe->ProbingParserTs(f, direction, buf, buflen, rdir);
} else if (pe->ProbingParserTc != NULL) {
alproto = pe->ProbingParserTc(f, direction, buf, buflen, rdir);
}
if (AppProtoIsValid(alproto)) {
SCReturnUInt(alproto);
}
if (alproto == ALPROTO_FAILED ||
(pe->max_depth != 0 && buflen > pe->max_depth)) {
alproto_masks[0] |= pe->alproto_mask;
}
pe = pe->next;
}
SCReturnUInt(ALPROTO_UNKNOWN);
}
/**
* \brief Call the probing parser if it exists for this flow.
*
@ -453,22 +486,28 @@ static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto,
*/
static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
uint8_t *buf, uint32_t buflen,
uint8_t ipproto, uint8_t direction,
uint8_t ipproto, const uint8_t idir,
bool *reverse_flow)
{
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;
uint8_t dir = idir;
uint16_t dp = f->protodetect_dp ? f->protodetect_dp : FLOW_GET_DP(f);
uint16_t sp = FLOW_GET_SP(f);
const uint16_t dp = f->protodetect_dp ? f->protodetect_dp : f->dp;
const uint16_t sp = f->sp;
again_midstream:
if (idir != dir) {
SWAP_VARS(uint16_t, dp, sp); /* look up parsers in rev dir */
}
SCLogDebug("%u->%u %s", sp, dp,
(dir == STREAM_TOSERVER) ? "toserver" : "toclient");
if (direction & STREAM_TOSERVER) {
if (dir == STREAM_TOSERVER) {
/* first try the destination port */
pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
alproto_masks = &f->probing_parser_toserver_alproto_masks;
@ -515,82 +554,62 @@ static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
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;
(dir == STREAM_TOSERVER) ? "toserver":"toclient");
if (dir == idir)
FLOW_SET_PP_DONE(f, dir);
goto noparsers;
}
/* run the parser(s) */
/* run the parser(s): always call with original direction */
uint8_t rdir = 0;
pe = pe1;
while (pe != NULL) {
if ((buflen < pe->min_depth) ||
(alproto_masks[0] & pe->alproto_mask)) {
pe = pe->next;
continue;
}
alproto = PPGetProto(pe1, f, idir, buf, buflen, alproto_masks, &rdir);
if (AppProtoIsValid(alproto))
goto end;
alproto = PPGetProto(pe2, f, idir, buf, buflen, alproto_masks, &rdir);
if (AppProtoIsValid(alproto))
goto end;
if (direction & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
alproto = pe->ProbingParserTs(f, direction, buf, buflen, &rdir);
} else if (pe->ProbingParserTc != NULL) {
alproto = pe->ProbingParserTc(f, direction, buf, buflen, &rdir);
}
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;
/* get the mask we need for this direction */
if (dir == idir) {
if (pp_port_dp && pp_port_sp)
mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
else if (pp_port_dp)
mask = pp_port_dp->alproto_mask;
else if (pp_port_sp)
mask = pp_port_sp->alproto_mask;
if (alproto_masks[0] == mask) {
FLOW_SET_PP_DONE(f, dir);
SCLogDebug("%s, mask is now %08x, needed %08x, so done",
(dir == STREAM_TOSERVER) ? "toserver":"toclient",
alproto_masks[0], mask);
} else {
SCLogDebug("%s, mask is now %08x, need %08x",
(dir == STREAM_TOSERVER) ? "toserver":"toclient",
alproto_masks[0], mask);
}
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 && pe->ProbingParserTs != NULL) {
alproto = pe->ProbingParserTs(f, direction, buf, buflen, &rdir);
} else if (pe->ProbingParserTc != NULL) {
alproto = pe->ProbingParserTc(f, direction, buf, buflen, &rdir);
}
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;
noparsers:
if (stream_config.midstream == true && idir == dir) {
if (idir == STREAM_TOSERVER) {
dir = STREAM_TOCLIENT;
} else {
dir = STREAM_TOSERVER;
}
pe = pe->next;
}
/* get the mask we need for this direction */
if (pp_port_dp && pp_port_sp)
mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
else if (pp_port_dp)
mask = pp_port_dp->alproto_mask;
else if (pp_port_sp)
mask = pp_port_sp->alproto_mask;
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 {
SCLogDebug("%s, mask is now %08x, need %08x",
(direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0], mask);
SCLogDebug("no match + midstream, retry the other direction %s",
(dir == STREAM_TOSERVER) ? "toserver" : "toclient");
goto again_midstream;
}
end:
if (alproto != ALPROTO_FAILED && alproto != ALPROTO_UNKNOWN &&
rdir == (direction & (STREAM_TOSERVER|STREAM_TOCLIENT))) {
if (AppProtoIsValid(alproto) && rdir != 0 && rdir != idir) {
SCLogDebug("PP found %u, is reverse flow", alproto);
*reverse_flow = true;
}
SCLogDebug("%s, mask is now %08x",
(direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
(idir == STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
SCReturnUInt(alproto);
}
@ -1482,8 +1501,7 @@ AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx,
if (!FLOW_IS_PM_DONE(f, direction)) {
AppProto pm_results[ALPROTO_MAX];
uint16_t pm_matches = AppLayerProtoDetectPMGetProto(tctx, f,
buf, buflen, direction,
pm_results, reverse_flow);
buf, buflen, direction, pm_results, reverse_flow);
if (pm_matches > 0) {
alproto = pm_results[0];
@ -1500,13 +1518,13 @@ AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx,
if (!FLOW_IS_PP_DONE(f, direction)) {
bool rflow = false;
alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen,
ipproto, direction,
&rflow);
if (alproto != ALPROTO_UNKNOWN)
alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto,
direction & (STREAM_TOSERVER|STREAM_TOCLIENT), &rflow);
if (AppProtoIsValid(alproto)) {
if (rflow) {
*reverse_flow = true;
}
goto end;
if (rflow) {
*reverse_flow = true;
}
}
@ -1516,7 +1534,7 @@ AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx,
}
end:
if (alproto == ALPROTO_UNKNOWN)
if (!AppProtoIsValid(alproto))
alproto = pm_alproto;
SCReturnUInt(alproto);

Loading…
Cancel
Save