From 432c3317d296c714431f3b3e850bd92e01ddee89 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Mon, 19 Sep 2011 14:03:40 +0530 Subject: [PATCH] app layer probing parser updates --- src/app-layer-detect-proto.c | 58 +- src/app-layer-detect-proto.h | 1 + src/app-layer-parser.c | 1247 ++++++++++++++++++++++++++++++++-- src/app-layer-parser.h | 36 +- src/app-layer-protos.h | 1 + src/app-layer-smb.c | 9 +- src/detect-parse.c | 10 + src/flow-util.h | 4 + src/flow.h | 3 + 9 files changed, 1296 insertions(+), 73 deletions(-) diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index d884ee1603..c262d2fe69 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -247,6 +247,9 @@ void AlpProtoTestDestroy(AlpProtoDetectCtx *ctx) { mpm_table[ctx->toclient.mpm_ctx.mpm_type].DestroyCtx(&ctx->toclient.mpm_ctx); AlpProtoFreeSignature(ctx->head); AppLayerFreeProbingParsers(ctx->probing_parsers); + ctx->probing_parsers = NULL; + AppLayerFreeProbingParsersInfo(ctx->probing_parsers_info); + ctx->probing_parsers_info = NULL; } #endif @@ -256,6 +259,9 @@ void AlpProtoDestroy() { mpm_table[alp_proto_ctx.toclient.mpm_ctx.mpm_type].DestroyCtx(&alp_proto_ctx.toclient.mpm_ctx); MpmPatternIdTableFreeHash(alp_proto_ctx.mpm_pattern_id_store); AppLayerFreeProbingParsers(alp_proto_ctx.probing_parsers); + alp_proto_ctx.probing_parsers = NULL; + AppLayerFreeProbingParsersInfo(alp_proto_ctx.probing_parsers_info); + alp_proto_ctx.probing_parsers_info = NULL; SCReturn; } @@ -515,9 +521,11 @@ uint16_t AppLayerDetectGetProtoProbingParser(AlpProtoDetectCtx *ctx, Flow *f, AppLayerProbingParserElement *pe = NULL; AppLayerProbingParser *probing_parsers = ctx->probing_parsers; AppLayerProbingParser *pp = NULL; + uint16_t *al_proto_masks; if (flags & STREAM_TOSERVER) { pp = AppLayerGetProbingParsers(probing_parsers, ipproto, f->dp); + al_proto_masks = &f->probing_parser_toserver_al_proto_masks; if (pp == NULL) { SCLogDebug("toserver-No probing parser registered for port %"PRIu16, f->dp); @@ -528,17 +536,10 @@ uint16_t AppLayerDetectGetProtoProbingParser(AlpProtoDetectCtx *ctx, Flow *f, f->flags |= FLOW_TS_PP_ALPROTO_DETECT_DONE; return ALPROTO_UNKNOWN; } - if (pp->toserver_max_depth != 0 && buflen > pp->toserver_max_depth) { - if (f->flags & FLOW_TS_PM_ALPROTO_DETECT_DONE) { - f->flags |= FLOW_TS_PM_PP_ALPROTO_DETECT_DONE; - return ALPROTO_UNKNOWN; - } - f->flags |= FLOW_TS_PP_ALPROTO_DETECT_DONE; - return ALPROTO_UNKNOWN; - } pe = pp->toserver; } else { pp = AppLayerGetProbingParsers(probing_parsers, ipproto, f->sp); + al_proto_masks = &f->probing_parser_toclient_al_proto_masks; if (pp == NULL) { SCLogDebug("toclient-No probing parser registered for port %"PRIu16, f->sp); @@ -549,31 +550,46 @@ uint16_t AppLayerDetectGetProtoProbingParser(AlpProtoDetectCtx *ctx, Flow *f, f->flags |= FLOW_TC_PP_ALPROTO_DETECT_DONE; return ALPROTO_UNKNOWN; } - if (pp->toclient_max_depth != 0 && buflen > pp->toclient_max_depth) { - if (f->flags & FLOW_TC_PM_ALPROTO_DETECT_DONE) { - f->flags |= FLOW_TC_PM_PP_ALPROTO_DETECT_DONE; - return ALPROTO_UNKNOWN; - } - f->flags |= FLOW_TC_PP_ALPROTO_DETECT_DONE; - return ALPROTO_UNKNOWN; - } pe = pp->toclient; } + while (pe != NULL) { - if (buflen < pe->min_depth || - (pe->max_depth != 0 && buflen > pe->max_depth)) { + if ((buflen < pe->min_depth) || + al_proto_masks[0] & pe->al_proto_mask) { pe = pe->next; continue; } - uint16_t alproto = pe->ProbingParser(buf, buflen); - if (alproto != ALPROTO_UNKNOWN) + int alproto = pe->ProbingParser(buf, buflen); + if (alproto > ALPROTO_UNKNOWN) return alproto; - + if (alproto == -1 || (pe->max_depth != 0 && buflen > pe->max_depth)) { + al_proto_masks[0] |= pe->al_proto_mask; + } pe = pe->next; } + if (flags & STREAM_TOSERVER) { + if (al_proto_masks[0] == pp->toserver_al_proto_mask) { + if (f->flags & FLOW_TS_PM_ALPROTO_DETECT_DONE) { + f->flags |= FLOW_TS_PM_PP_ALPROTO_DETECT_DONE; + return ALPROTO_UNKNOWN; + } + f->flags |= FLOW_TS_PP_ALPROTO_DETECT_DONE; + return ALPROTO_UNKNOWN; + } + } else { + if (al_proto_masks[0] == pp->toclient_al_proto_mask) { + if (f->flags & FLOW_TC_PM_ALPROTO_DETECT_DONE) { + f->flags |= FLOW_TC_PM_PP_ALPROTO_DETECT_DONE; + return ALPROTO_UNKNOWN; + } + f->flags |= FLOW_TC_PP_ALPROTO_DETECT_DONE; + return ALPROTO_UNKNOWN; + } + } + return ALPROTO_UNKNOWN; } diff --git a/src/app-layer-detect-proto.h b/src/app-layer-detect-proto.h index 565e2cd8dc..9534d35955 100644 --- a/src/app-layer-detect-proto.h +++ b/src/app-layer-detect-proto.h @@ -74,6 +74,7 @@ typedef struct AlpProtoDetectCtx_ { AlpProtoSignature *head; /**< list of sigs */ AppLayerProbingParser *probing_parsers; + AppLayerProbingParserInfo *probing_parsers_info; uint16_t sigs; /**< number of sigs */ } AlpProtoDetectCtx; diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 6ed9c5f258..546160dcba 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -948,11 +948,13 @@ error: PrintInet(AF_INET, (const void*)&f->dst.addr_data32[0], dst, sizeof (dst)); - SCLogError(SC_ERR_ALPARSER, "Error occured in parsing \"%s\" app layer " - "protocol, using network protocol %"PRIu8", source IP " - "address %s, destination IP address %s, src port %"PRIu16" and " - "dst port %"PRIu16"", al_proto_table[f->alproto].name, - f->proto, src, dst, f->sp, f->dp); + SCLogError(SC_ERR_ALPARSER, "Error occured in parsing " + "\"%s\" app layer " + "protocol, using network protocol %"PRIu8", source IP " + "address %s, destination IP address %s, src port %"PRIu16" and " + "dst port %"PRIu16"", al_proto_table[f->alproto].name, + f->proto, src, dst, f->sp, f->dp); + fflush(stdout); } else { char dst6[46]; char src6[46]; @@ -962,11 +964,13 @@ error: PrintInet(AF_INET6, (const void*)&f->dst.addr_data32, dst6, sizeof (dst6)); - SCLogError(SC_ERR_ALPARSER, "Error occured in parsing \"%s\" app layer " - "protocol, using network protocol %"PRIu8", source IPv6 " - "address %s, destination IPv6 address %s, src port %"PRIu16" and " - "dst port %"PRIu16"", al_proto_table[f->alproto].name, - f->proto, src6, dst6, f->sp, f->dp); + SCLogError(SC_ERR_ALPARSER, "Error occured in parsing " + "\"%s\" app layer " + "protocol, using network protocol %"PRIu8", source IPv6 " + "address %s, destination IPv6 address %s, src port %"PRIu16" and " + "dst port %"PRIu16"", al_proto_table[f->alproto].name, + f->proto, src6, dst6, f->sp, f->dp); + fflush(stdout); } } @@ -1339,18 +1343,67 @@ void AppLayerParsersInitPostProcess(void) /********************************Probing Parsers*******************************/ -//AppLayerProbingParser *probing_parsers = NULL; + +#define ALPROTO_PROBING_PARSER_MASK_HTTP 0x0001 +#define ALPROTO_PROBING_PARSER_MASK_FTP 0x0002 +#define ALPROTO_PROBING_PARSER_MASK_SMTP 0x0004 +#define ALPROTO_PROBING_PARSER_MASK_TLS 0x0008 +#define ALPROTO_PROBING_PARSER_MASK_SSH 0x0010 +#define ALPROTO_PROBING_PARSER_MASK_IMAP 0x0020 +#define ALPROTO_PROBING_PARSER_MASK_MSN 0x0040 +#define ALPROTO_PROBING_PARSER_MASK_JABBER 0x0080 +#define ALPROTO_PROBING_PARSER_MASK_SMB 0x0100 +#define ALPROTO_PROBING_PARSER_MASK_SMB2 0x0200 +#define ALPROTO_PROBING_PARSER_MASK_DCERPC 0x0400 +#define ALPROTO_PROBING_PARSER_MASK_DCERPC_UDP 0x0800 +#define ALPROTO_PROBING_PARSER_MASK_IRC 0x1000 + +static uint16_t AppLayerProbingParserGetMask(uint16_t al_proto) +{ + if (al_proto == ALPROTO_HTTP) { + return ALPROTO_PROBING_PARSER_MASK_HTTP; + } else if (al_proto == ALPROTO_FTP) { + return ALPROTO_PROBING_PARSER_MASK_FTP; + } else if (al_proto == ALPROTO_SMTP) { + return ALPROTO_PROBING_PARSER_MASK_SMTP; + } else if (al_proto == ALPROTO_TLS) { + return ALPROTO_PROBING_PARSER_MASK_TLS; + } else if (al_proto == ALPROTO_SSH) { + return ALPROTO_PROBING_PARSER_MASK_SSH; + } else if (al_proto == ALPROTO_IMAP) { + return ALPROTO_PROBING_PARSER_MASK_IMAP; + } else if (al_proto == ALPROTO_MSN) { + return ALPROTO_PROBING_PARSER_MASK_MSN; + } else if (al_proto == ALPROTO_JABBER) { + return ALPROTO_PROBING_PARSER_MASK_JABBER; + } else if (al_proto == ALPROTO_SMB) { + return ALPROTO_PROBING_PARSER_MASK_SMB; + } else if (al_proto == ALPROTO_SMB2) { + return ALPROTO_PROBING_PARSER_MASK_SMB2; + } else if (al_proto == ALPROTO_DCERPC) { + return ALPROTO_PROBING_PARSER_MASK_DCERPC; + } else if (al_proto == ALPROTO_DCERPC_UDP) { + return ALPROTO_PROBING_PARSER_MASK_DCERPC_UDP; + } else if (al_proto == ALPROTO_IRC) { + return ALPROTO_PROBING_PARSER_MASK_IRC; + } else { + SCLogError(SC_ERR_ALPARSER, "Unknown protocol detected - %"PRIu16, + al_proto); + exit(EXIT_FAILURE); + } +} static AppLayerProbingParserElement * AppLayerCreateAppLayerProbingParserElement(const char *al_proto_name, + uint16_t ip_proto, uint16_t al_proto, uint16_t min_depth, uint16_t max_depth, uint16_t port, uint8_t priority, uint8_t top, - uint16_t (*AppLayerProbingParser) - (uint8_t *input, uint32_t input_len)) + int16_t (*AppLayerProbingParser) + (uint8_t *input, int32_t input_len)) { AppLayerProbingParserElement *pe = SCMalloc(sizeof(AppLayerProbingParserElement)); if (pe == NULL) { @@ -1358,7 +1411,9 @@ AppLayerCreateAppLayerProbingParserElement(const char *al_proto_name, } pe->al_proto_name = al_proto_name; + pe->ip_proto = ip_proto; pe->al_proto = al_proto; + pe->al_proto_mask = AppLayerProbingParserGetMask(al_proto); pe->min_depth = min_depth; pe->max_depth = max_depth; pe->port = port; @@ -1389,18 +1444,43 @@ AppLayerCreateAppLayerProbingParserElement(const char *al_proto_name, return NULL; } -static void AppLayerInsertNewProbingParserElement(AppLayerProbingParser **probing_parsers, - AppLayerProbingParserElement *new_pe, - uint8_t flags) +static AppLayerProbingParserElement * +AppLayerDuplicateAppLayerProbingParserElement(AppLayerProbingParserElement *pe) { - AppLayerProbingParser *pp = probing_parsers[0]; - while (pp != NULL) { - if (pp->port == new_pe->port) { - break; - } - pp = pp->next; + AppLayerProbingParserElement *new_pe = SCMalloc(sizeof(AppLayerProbingParserElement)); + if (pe == NULL) { + return NULL; } + new_pe->al_proto_name = pe->al_proto_name; + new_pe->ip_proto = pe->ip_proto; + new_pe->al_proto = pe->al_proto; + new_pe->al_proto_mask = pe->al_proto_mask; + new_pe->min_depth = pe->min_depth; + new_pe->max_depth = pe->max_depth; + new_pe->port = pe->port; + new_pe->priority = pe->priority; + new_pe->top = pe->top; + new_pe->ProbingParser = pe->ProbingParser; + new_pe->next = NULL; + + return new_pe; +} + +static void +AppLayerFreeAppLayerProbingParserElement(AppLayerProbingParserElement *pe) +{ + SCFree(pe); + + return; +} + +static void +AppLayerInsertNewProbingParserSingleElement(AppLayerProbingParser *pp, + AppLayerProbingParser **probing_parsers, + AppLayerProbingParserElement *new_pe, + uint8_t flags) +{ if (pp == NULL) { AppLayerProbingParser *new_pp = SCMalloc(sizeof(AppLayerProbingParser)); if (new_pp == NULL) @@ -1413,10 +1493,18 @@ static void AppLayerInsertNewProbingParserElement(AppLayerProbingParser **probin probing_parsers[0] = new_pp; } else { AppLayerProbingParser *pp = probing_parsers[0]; - while (pp->next != NULL) { - pp = pp->next; + if (pp->port == 0) { + new_pp->next = probing_parsers[0]; + probing_parsers[0] = new_pp; + } else { + /* port 0 based pp is always the last one. Hence the + * premature exit condition if port is 0 */ + while (pp->next != NULL && pp->next->port != 0) { + pp = pp->next; + } + new_pp->next = pp->next; + pp->next = new_pp; } - pp->next = new_pp; } pp = new_pp; @@ -1489,6 +1577,76 @@ static void AppLayerInsertNewProbingParserElement(AppLayerProbingParser **probin } /* else - if (pe == NULL) */ + if (flags & STREAM_TOSERVER) + pp->toserver_al_proto_mask |= new_pe->al_proto_mask; + else + pp->toclient_al_proto_mask |= new_pe->al_proto_mask; + + return; +} + +static void AppLayerInsertNewProbingParserElement(AppLayerProbingParser **probing_parsers, + AppLayerProbingParserElement *new_pe, + uint8_t flags) +{ + AppLayerProbingParser *pp = probing_parsers[0]; + + if (new_pe->port != 0) { + AppLayerProbingParser *zero_pp = NULL; + while (pp != NULL) { + if (pp->port == new_pe->port) { + break; + } + if (pp->port == 0) + zero_pp = pp; + pp = pp->next; + } + AppLayerInsertNewProbingParserSingleElement(pp, probing_parsers, new_pe, + flags); + if (zero_pp != NULL) { + pp = probing_parsers[0]; + while (pp != NULL) { + if (pp->port == new_pe->port) + break; + pp = pp->next; + } + BUG_ON(pp == NULL); + AppLayerProbingParserElement *temp_pe; + if (flags & STREAM_TOSERVER) { + temp_pe = zero_pp->toserver; + } else { + temp_pe = zero_pp->toclient; + } + while (temp_pe != NULL) { + AppLayerProbingParserElement *dup_pe = + AppLayerDuplicateAppLayerProbingParserElement(temp_pe); + AppLayerInsertNewProbingParserSingleElement(pp, probing_parsers, dup_pe, + flags); + temp_pe = temp_pe->next; + } + } + + } else { + int zero_port_present = 0; + while (pp != NULL) { + AppLayerProbingParserElement *dup_pe = + AppLayerDuplicateAppLayerProbingParserElement(new_pe); + + AppLayerInsertNewProbingParserSingleElement(pp, probing_parsers, dup_pe, + flags); + if (pp->port == 0) + zero_port_present = 1; + pp = pp->next; + } + + if (zero_port_present == 0) { + AppLayerInsertNewProbingParserSingleElement(NULL, probing_parsers, new_pe, + flags); + } else { + SCFree(new_pe); + } + } + return; } @@ -1499,7 +1657,9 @@ void AppLayerPrintProbingParsers(AppLayerProbingParser *pp) printf("\n"); while (pp != NULL) { printf("Port: %"PRIu16 "\n", pp->port); - printf(" to_server: max-depth: %"PRIu16 "\n", pp->toserver_max_depth); + printf(" to_server: max-depth: %"PRIu16 ", " + "mask - %"PRIu16"\n", pp->toserver_max_depth, + pp->toserver_al_proto_mask); pe = pp->toserver; while (pe != NULL) { printf(" name: %s\n", pe->al_proto_name); @@ -1528,6 +1688,8 @@ void AppLayerPrintProbingParsers(AppLayerProbingParser *pp) printf(" alproto: ALPROTO_DCERPC\n"); else if (pe->al_proto == ALPROTO_DCERPC_UDP) printf(" alproto: ALPROTO_DCERPC_UDP\n"); + else if (pe->al_proto == ALPROTO_IRC) + printf(" alproto: ALPROTO_IRC\n"); else printf("impossible\n"); @@ -1546,17 +1708,81 @@ void AppLayerPrintProbingParsers(AppLayerProbingParser *pp) printf(" min_depth: %"PRIu32 "\n", pe->min_depth); printf(" max_depth: %"PRIu32 "\n", pe->max_depth); + printf(" mask: %"PRIu16 "\n", pe->al_proto_mask); printf("\n"); pe = pe->next; } - printf(" to_client: max-depth: %"PRIu16 "\n", pp->toclient_max_depth); pp = pp->next; } return; } +int AppLayerProbingParserInfoAdd(AlpProtoDetectCtx *ctx, + const char *al_proto_name, + uint16_t ip_proto, + uint16_t al_proto, + int16_t (*ProbingParser) + (uint8_t *input, int32_t input_len)) +{ + AppLayerProbingParserInfo *new_ppi = NULL; + + AppLayerProbingParserInfo *ppi = ctx->probing_parsers_info; + while (ppi != NULL) { + if (strcmp(ppi->al_proto_name, al_proto_name) == 0) + break; + ppi = ppi->next; + } + + if (ppi == NULL) { + new_ppi = SCMalloc(sizeof(AppLayerProbingParserInfo)); + if (new_ppi == NULL) { + return -1; + } + memset(new_ppi, 0, sizeof(AppLayerProbingParserInfo)); + new_ppi->al_proto_name = al_proto_name; + new_ppi->ip_proto = ip_proto; + new_ppi->al_proto = al_proto; + new_ppi->ProbingParser = ProbingParser; + + if (ctx->probing_parsers_info == NULL) { + ctx->probing_parsers_info = new_ppi; + } else { + new_ppi->next = ctx->probing_parsers_info; + ctx->probing_parsers_info = new_ppi; + } + return 0; + } + + if (ppi->ip_proto != ip_proto) { + SCLogError(SC_ERR_ALPARSER, "New probing parser \"%s\" being registered " + "already exists in the database of registered parsers, " + "except that the new one registers with a different ip_proto" + " %"PRIu16" compared to the existing entry of %"PRIu16, + ppi->al_proto_name, ppi->ip_proto, ip_proto); + return -1; + } + if (ppi->al_proto != al_proto) { + SCLogError(SC_ERR_ALPARSER, "New probing parser \"%s\" being registered " + "already exists in the database of registered parsers, " + "except that the new one registers with a different alproto " + "%"PRIu16" compared to the existing entry of %"PRIu16, + ppi->al_proto_name, ppi->al_proto, al_proto); + return -1; + } + if (ppi->ProbingParser != ProbingParser) { + SCLogError(SC_ERR_ALPARSER, "New probing parser \"%s\" being registered " + "already exists in the database of registered parsers, " + "except that the new one registers with a differnt " + "ProbingParser function compared to the existing entry " + "in the database", ppi->al_proto_name); + return -1; + } + + return 0; +} + void AppLayerRegisterProbingParser(AlpProtoDetectCtx *ctx, uint16_t port, uint16_t ip_proto, @@ -1567,13 +1793,33 @@ void AppLayerRegisterProbingParser(AlpProtoDetectCtx *ctx, uint8_t flags, uint8_t priority, uint8_t top, - uint16_t (*ProbingParser) - (uint8_t *input, uint32_t input_len)) + int16_t (*ProbingParser) + (uint8_t *input, int32_t input_len)) { AppLayerProbingParser **probing_parsers = &ctx->probing_parsers; AppLayerProbingParserElement *pe = NULL; - AppLayerProbingParser *pp = AppLayerGetProbingParsers(probing_parsers[0], - ip_proto, port); + AppLayerProbingParser *pp = NULL; + + /* Add info about this probing parser to our database. Also detects any + * duplicate existance of this parser but with conflicting parameters */ + if (AppLayerProbingParserInfoAdd(ctx, al_proto_name, ip_proto, al_proto, + ProbingParser) < 0) { + goto error; + } + + /* \todo introduce parsing port range here */ + + /* Get a new parser element */ + AppLayerProbingParserElement *new_pe = + AppLayerCreateAppLayerProbingParserElement(al_proto_name, ip_proto, + al_proto, min_depth, + max_depth, port, + priority, top, + ProbingParser); + if (new_pe == NULL) + goto error; + + pp = AppLayerGetProbingParsers(probing_parsers[0], ip_proto, port); if (pp != NULL) { if (flags & STREAM_TOSERVER) { pe = pp->toserver; @@ -1591,22 +1837,32 @@ void AppLayerRegisterProbingParser(AlpProtoDetectCtx *ctx, /* looks like we have it registered for this port + dir */ SCLogWarning(SC_ERR_ALPARSER, "App layer probing parser already " "registered for this port, direction"); - return; + goto error; } tmp_pe = tmp_pe->next; } } - /* Get a new parser element */ - AppLayerProbingParserElement *new_pe = - AppLayerCreateAppLayerProbingParserElement(al_proto_name, al_proto, - min_depth, max_depth, - port, priority, top, - ProbingParser); - if (new_pe == NULL) - return; - AppLayerInsertNewProbingParserElement(probing_parsers, new_pe, flags); + + return; + error: + if (new_pe != NULL) + SCFree(new_pe); + return; +} + +void AppLayerFreeProbingParsersInfo(AppLayerProbingParserInfo *probing_parsers_info) +{ + AppLayerProbingParserInfo *ppi = probing_parsers_info; + AppLayerProbingParserInfo *next_ppi = NULL; + + while (ppi != NULL) { + next_ppi = ppi->next; + SCFree(ppi); + ppi = next_ppi; + } + return; } @@ -1619,14 +1875,14 @@ void AppLayerFreeProbingParsers(AppLayerProbingParser *probing_parsers) pe = probing_parsers->toserver; while (pe != NULL) { next_pe = pe->next; - SCFree(pe); + AppLayerFreeAppLayerProbingParserElement(pe); pe = next_pe; } pe = probing_parsers->toclient; while (pe != NULL) { next_pe = pe->next; - SCFree(pe); + AppLayerFreeAppLayerProbingParserElement(pe); pe = next_pe; } @@ -1795,7 +2051,7 @@ end: return result; } -uint16_t ProbingParserDummyForTesting(uint8_t *input, uint32_t input_len) +int16_t ProbingParserDummyForTesting(uint8_t *input, int32_t input_len) { return 0; } @@ -1856,6 +2112,8 @@ static int AppLayerProbingParserTest02(void) goto end; if (pp->toserver->next != NULL) goto end; + if (pp->toserver_al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) + goto end; /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "http") != 0) @@ -1872,6 +2130,8 @@ static int AppLayerProbingParserTest02(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) + goto end; AppLayerRegisterProbingParser(&ctx, 80, @@ -1902,6 +2162,10 @@ static int AppLayerProbingParserTest02(void) goto end; if (pp->toserver->next->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP | + ALPROTO_PROBING_PARSER_MASK_SMB)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "smb") != 0) @@ -1918,6 +2182,9 @@ static int AppLayerProbingParserTest02(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_SMB) { + goto end; + } /* second one */ pe = pp->toserver->next; if (strcmp(pe->al_proto_name, "http") != 0) @@ -1934,6 +2201,9 @@ static int AppLayerProbingParserTest02(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } AppLayerRegisterProbingParser(&ctx, 80, @@ -1966,6 +2236,12 @@ static int AppLayerProbingParserTest02(void) goto end; if (pp->toserver->next->next->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP | + ALPROTO_PROBING_PARSER_MASK_SMB | + ALPROTO_PROBING_PARSER_MASK_DCERPC)) { + goto end; + } + /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "dcerpc") != 0) @@ -1982,6 +2258,9 @@ static int AppLayerProbingParserTest02(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_DCERPC) { + goto end; + } /* second one */ pe = pp->toserver->next; if (strcmp(pe->al_proto_name, "smb") != 0) @@ -1998,6 +2277,9 @@ static int AppLayerProbingParserTest02(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_SMB) { + goto end; + } /* third one */ pe = pp->toserver->next->next; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2014,6 +2296,9 @@ static int AppLayerProbingParserTest02(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } result = 1; @@ -2058,6 +2343,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pp->toserver->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2074,6 +2362,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } AppLayerRegisterProbingParser(&ctx, 80, @@ -2104,6 +2395,10 @@ static int AppLayerProbingParserTest03(void) goto end; if (pp->toserver->next->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP | + ALPROTO_PROBING_PARSER_MASK_SMB)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2120,6 +2415,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } /* second one */ pe = pp->toserver->next; if (strcmp(pe->al_proto_name, "smb") != 0) @@ -2136,6 +2434,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_SMB) { + goto end; + } AppLayerRegisterProbingParser(&ctx, 80, @@ -2168,6 +2469,11 @@ static int AppLayerProbingParserTest03(void) goto end; if (pp->toserver->next->next->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP | + ALPROTO_PROBING_PARSER_MASK_DCERPC | + ALPROTO_PROBING_PARSER_MASK_SMB)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2184,6 +2490,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } /* second one */ pe = pp->toserver->next; if (strcmp(pe->al_proto_name, "smb") != 0) @@ -2200,6 +2509,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_SMB) { + goto end; + } /* third one */ pe = pp->toserver->next->next; if (strcmp(pe->al_proto_name, "dcerpc") != 0) @@ -2216,6 +2528,9 @@ static int AppLayerProbingParserTest03(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_DCERPC) { + goto end; + } result = 1; @@ -2260,6 +2575,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pp->toserver->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2276,6 +2594,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } AppLayerRegisterProbingParser(&ctx, 80, @@ -2306,6 +2627,10 @@ static int AppLayerProbingParserTest04(void) goto end; if (pp->toserver->next->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP | + ALPROTO_PROBING_PARSER_MASK_SMB)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "smb") != 0) @@ -2322,6 +2647,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_SMB) { + goto end; + } /* second one */ pe = pp->toserver->next; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2338,6 +2666,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } AppLayerRegisterProbingParser(&ctx, 80, @@ -2370,6 +2701,11 @@ static int AppLayerProbingParserTest04(void) goto end; if (pp->toserver->next->next->next != NULL) goto end; + if (pp->toserver_al_proto_mask != (ALPROTO_PROBING_PARSER_MASK_HTTP | + ALPROTO_PROBING_PARSER_MASK_DCERPC | + ALPROTO_PROBING_PARSER_MASK_SMB)) { + goto end; + } /* first one */ pe = pp->toserver; if (strcmp(pe->al_proto_name, "smb") != 0) @@ -2386,6 +2722,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_SMB) { + goto end; + } /* second one */ pe = pp->toserver->next; if (strcmp(pe->al_proto_name, "http") != 0) @@ -2402,6 +2741,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_HTTP) { + goto end; + } /* third one */ pe = pp->toserver->next->next; if (strcmp(pe->al_proto_name, "dcerpc") != 0) @@ -2418,6 +2760,9 @@ static int AppLayerProbingParserTest04(void) goto end; if (pe->ProbingParser != ProbingParserDummyForTesting) goto end; + if (pe->al_proto_mask != ALPROTO_PROBING_PARSER_MASK_DCERPC) { + goto end; + } result = 1; @@ -4650,6 +4995,818 @@ static int AppLayerProbingParserTest13(void) return result; } +static int AppLayerProbingParserTest14(void) +{ + int result = 0; + AppLayerProbingParser *pp; + AppLayerProbingParserElement *pe; + + AlpProtoDetectCtx ctx; + AlpProtoInit(&ctx); + + AppLayerRegisterProbingParser(&ctx, + 80, + IPPROTO_TCP, + "http", + ALPROTO_HTTP, + 5, 8, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 1, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 8) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerRegisterProbingParser(&ctx, + 80, + IPPROTO_TCP, + "smb", + ALPROTO_SMB, + 5, 15, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 0, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 15) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "smb") != 0) + goto end; + if (pe->al_proto != ALPROTO_SMB) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerRegisterProbingParser(&ctx, + 0, + IPPROTO_TCP, + "dcerpc", + ALPROTO_DCERPC, + 5, 25, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 0, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next == NULL) + goto end; + if (pp->next->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next == NULL) + goto end; + if (pp->toserver->next->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "smb") != 0) + goto end; + if (pe->al_proto != ALPROTO_SMB) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + pe = pp->toserver->next->next; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second probing parser */ + pp = pp->next; + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 0) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerRegisterProbingParser(&ctx, + 81, + IPPROTO_TCP, + "ftp", + ALPROTO_FTP, + 7, 50, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 1, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next == NULL) + goto end; + if (pp->next->next == NULL) + goto end; + if (pp->next->next->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next == NULL) + goto end; + if (pp->toserver->next->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "smb") != 0) + goto end; + if (pe->al_proto != ALPROTO_SMB) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + pe = pp->toserver->next->next; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + /* second probing parser */ + pp = pp->next; + if (pp->toclient != NULL) + goto end; + if (pp->next == NULL) + goto end; + if (pp->next->next != NULL) + goto end; + if (pp->port != 81) + goto end; + if (pp->toserver_max_depth != 50) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "ftp") != 0) + goto end; + if (pe->al_proto != ALPROTO_FTP) + goto end; + if (pe->port != 81) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 7) + goto end; + if (pe->max_depth != 50) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + /* third probing parser */ + pp = pp->next; + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 0) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerPrintProbingParsers(ctx.probing_parsers); + + result = 1; + + end: + AlpProtoTestDestroy(&ctx); + return result; +} + +static int AppLayerProbingParserTest15(void) +{ + int result = 0; + AppLayerProbingParser *pp; + AppLayerProbingParserElement *pe; + + AlpProtoDetectCtx ctx; + AlpProtoInit(&ctx); + + AppLayerRegisterProbingParser(&ctx, + 80, + IPPROTO_TCP, + "http", + ALPROTO_HTTP, + 5, 8, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 1, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 8) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerRegisterProbingParser(&ctx, + 80, + IPPROTO_TCP, + "smb", + ALPROTO_SMB, + 5, 15, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 0, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 15) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "smb") != 0) + goto end; + if (pe->al_proto != ALPROTO_SMB) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerRegisterProbingParser(&ctx, + 0, + IPPROTO_TCP, + "dcerpc", + ALPROTO_DCERPC, + 5, 25, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 0, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next == NULL) + goto end; + if (pp->next->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next == NULL) + goto end; + if (pp->toserver->next->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "smb") != 0) + goto end; + if (pe->al_proto != ALPROTO_SMB) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + pe = pp->toserver->next->next; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second probing parser */ + pp = pp->next; + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 0) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerRegisterProbingParser(&ctx, + 81, + IPPROTO_TCP, + "ftp", + ALPROTO_FTP, + 7, 15, + STREAM_TOSERVER, + APP_LAYER_PROBING_PARSER_PRIORITY_HIGH, 1, + ProbingParserDummyForTesting); + pp = ctx.probing_parsers; + if (ctx.probing_parsers == NULL) { + goto end; + } + if (pp->toclient != NULL) + goto end; + if (pp->next == NULL) + goto end; + if (pp->next->next == NULL) + goto end; + if (pp->next->next->next != NULL) + goto end; + if (pp->port != 80) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next == NULL) + goto end; + if (pp->toserver->next->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "http") != 0) + goto end; + if (pe->al_proto != ALPROTO_HTTP) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 8) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "smb") != 0) + goto end; + if (pe->al_proto != ALPROTO_SMB) + goto end; + if (pe->port != 80) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + pe = pp->toserver->next->next; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + /* second probing parser */ + pp = pp->next; + if (pp->toclient != NULL) + goto end; + if (pp->next == NULL) + goto end; + if (pp->next->next != NULL) + goto end; + if (pp->port != 81) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next == NULL) + goto end; + if (pp->toserver->next->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "ftp") != 0) + goto end; + if (pe->al_proto != ALPROTO_FTP) + goto end; + if (pe->port != 81) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 7) + goto end; + if (pe->max_depth != 15) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + /* second one */ + pe = pp->toserver->next; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + /* third probing parser */ + pp = pp->next; + if (pp->toclient != NULL) + goto end; + if (pp->next != NULL) + goto end; + if (pp->port != 0) + goto end; + if (pp->toserver_max_depth != 25) + goto end; + if (pp->toclient_max_depth != 0) + goto end; + if (pp->toserver == NULL) + goto end; + if (pp->toserver->next != NULL) + goto end; + /* first one */ + pe = pp->toserver; + if (strcmp(pe->al_proto_name, "dcerpc") != 0) + goto end; + if (pe->al_proto != ALPROTO_DCERPC) + goto end; + if (pe->port != 0) + goto end; + if (pe->priority != APP_LAYER_PROBING_PARSER_PRIORITY_HIGH) + goto end; + if (pe->min_depth != 5) + goto end; + if (pe->max_depth != 25) + goto end; + if (pe->ProbingParser != ProbingParserDummyForTesting) + goto end; + + AppLayerPrintProbingParsers(ctx.probing_parsers); + + result = 1; + + end: + AlpProtoTestDestroy(&ctx); + return result; +} + #endif /* UNITESTS */ void AppLayerParserRegisterTests(void) @@ -4670,6 +5827,8 @@ void AppLayerParserRegisterTests(void) UtRegisterTest("AppLayerProbingParserTest11", AppLayerProbingParserTest11, 1); UtRegisterTest("AppLayerProbingParserTest12", AppLayerProbingParserTest12, 1); UtRegisterTest("AppLayerProbingParserTest13", AppLayerProbingParserTest13, 1); + UtRegisterTest("AppLayerProbingParserTest14", AppLayerProbingParserTest14, 1); + UtRegisterTest("AppLayerProbingParserTest15", AppLayerProbingParserTest15, 1); #endif /* UNITTESTS */ return; diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 55b34a0b86..6ef4e91e5c 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -139,14 +139,16 @@ typedef struct AppLayerProbingParserElement_ { const char *al_proto_name; uint16_t al_proto; uint16_t port; + uint16_t ip_proto; uint8_t priority; uint8_t top; + uint16_t al_proto_mask; /* the min length of data that has to be supplied to invoke the parser */ uint32_t min_depth; /* the max length of data after which this parser won't be invoked */ uint32_t max_depth; /* the probing parser function */ - uint16_t (*ProbingParser)(uint8_t *input, uint32_t input_len); + int16_t (*ProbingParser)(uint8_t *input, int32_t input_len); struct AppLayerProbingParserElement_ *next; } AppLayerProbingParserElement; @@ -154,6 +156,8 @@ typedef struct AppLayerProbingParserElement_ { typedef struct AppLayerProbingParser_ { /* the port no for which probing parser(s) are invoked */ uint16_t port; + uint16_t toserver_al_proto_mask; + uint16_t toclient_al_proto_mask; /* the max depth for all the probing parsers registered for this port */ uint16_t toserver_max_depth; uint16_t toclient_max_depth; @@ -164,6 +168,14 @@ typedef struct AppLayerProbingParser_ { struct AppLayerProbingParser_ *next; } AppLayerProbingParser; +typedef struct AppLayerProbingParserInfo_ { + const char *al_proto_name; + uint16_t ip_proto; + uint16_t al_proto; + int16_t (*ProbingParser)(uint8_t *input, int32_t input_len); + struct AppLayerProbingParserInfo_ *next; +} AppLayerProbingParserInfo; + #define APP_LAYER_PROBING_PARSER_PRIORITY_HIGH 1 #define APP_LAYER_PROBING_PARSER_PRIORITY_MEDIUM 2 #define APP_LAYER_PROBING_PARSER_PRIORITY_LOW 3 @@ -178,7 +190,7 @@ AppLayerProbingParser *AppLayerGetProbingParsers(AppLayerProbingParser *probing_ AppLayerProbingParser *pp = probing_parsers; while (pp != NULL) { - if (pp->port == port) { + if (pp->port == port || pp->port == 0) { break; } pp = pp->next; @@ -187,6 +199,19 @@ AppLayerProbingParser *AppLayerGetProbingParsers(AppLayerProbingParser *probing_ return pp; } +static inline +AppLayerProbingParserInfo *AppLayerGetProbingParserInfo(AppLayerProbingParserInfo *ppi, + const char *al_proto_name) +{ + while (ppi != NULL) { + if (strcmp(ppi->al_proto_name, al_proto_name) == 0) + return ppi; + ppi = ppi->next; + } + + return NULL; +} + struct AlpProtoDetectCtx_; /* prototypes */ @@ -205,8 +230,8 @@ int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id, void AppLayerRegisterProbingParser(struct AlpProtoDetectCtx_ *, uint16_t, uint16_t, const char *, uint16_t, uint16_t, uint16_t, uint8_t, uint8_t, - uint8_t, uint16_t (*ProbingParser) - (uint8_t *, uint32_t)); + uint8_t, + int16_t (*ProbingParser)(uint8_t *, int32_t)); void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void), void (*StateFree)(void *)); void AppLayerRegisterTransactionIdFuncs(uint16_t proto, @@ -243,8 +268,9 @@ void AppLayerParserCleanupState(Flow *); uint8_t AppLayerRegisterModule(void); uint8_t AppLayerGetStorageSize(void); void AppLayerFreeProbingParsers(AppLayerProbingParser *); +void AppLayerFreeProbingParsersInfo(AppLayerProbingParserInfo *); +void AppLayerPrintProbingParsers(AppLayerProbingParser *); uint16_t AppLayerGetStateVersion(Flow *f); #endif /* __APP_LAYER_PARSER_H__ */ - diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 39826c3d5e..59790103b2 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -38,6 +38,7 @@ enum { ALPROTO_SMB2, ALPROTO_DCERPC, ALPROTO_DCERPC_UDP, + ALPROTO_IRC, #ifdef UNITTESTS ALPROTO_TEST, #endif /* UNITESTS */ diff --git a/src/app-layer-smb.c b/src/app-layer-smb.c index 001451810e..bb707c0783 100644 --- a/src/app-layer-smb.c +++ b/src/app-layer-smb.c @@ -1328,9 +1328,9 @@ void SMBUpdateTransactionId(void *state, uint16_t *id) { #define SMB_PROBING_PARSER_MIN_DEPTH 8 -static uint16_t SMBProbingParser(uint8_t *input, uint32_t input_len) +static int16_t SMBProbingParser(uint8_t *input, int32_t input_len) { - uint32_t len; + int32_t len; while (input_len >= SMB_PROBING_PARSER_MIN_DEPTH) { switch (input[0]) { @@ -1350,7 +1350,10 @@ static uint16_t SMBProbingParser(uint8_t *input, uint32_t input_len) len |= input[3]; break; default: - return ALPROTO_UNKNOWN; + /* -1 indicates a stream where the probing parser would be + * unable to find nbss, even if it exists. This should + * prevent the probing parser from beig invoked henceforth */ + return -1; } input_len -= 4; diff --git a/src/detect-parse.c b/src/detect-parse.c index 20197de106..7d6e6e4886 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -786,6 +786,16 @@ int SigParseProto(Signature *s, const char *protostr) { } SCReturnInt(0); } + AppLayerProbingParserInfo *ppi = + AppLayerGetProbingParserInfo(alp_proto_ctx.probing_parsers_info, + protostr); + if (ppi != NULL) { + /* indicate that the signature is app-layer */ + s->flags |= SIG_FLAG_APPLAYER; + s->alproto = ppi->al_proto; + s->proto.proto[ppi->ip_proto / 8] |= 1 << (ppi->ip_proto % 8); + SCReturnInt(0); + } SCLogError(SC_ERR_UNKNOWN_PROTOCOL, "protocol \"%s\" cannot be used " "in a signature", protostr); diff --git a/src/flow-util.h b/src/flow-util.h index 984368d094..8716862eac 100644 --- a/src/flow-util.h +++ b/src/flow-util.h @@ -47,6 +47,8 @@ SCMutexInit(&(f)->m, NULL); \ (f)->protoctx = NULL; \ (f)->alproto = 0; \ + (f)->probing_parser_toserver_al_proto_masks = 0; \ + (f)->probing_parser_toclient_al_proto_masks = 0; \ (f)->aldata = NULL; \ (f)->de_state = NULL; \ (f)->sgh_toserver = NULL; \ @@ -75,6 +77,8 @@ (f)->protoctx = NULL; \ FlowL7DataPtrFree(f); \ (f)->alproto = 0; \ + (f)->probing_parser_toserver_al_proto_masks = 0; \ + (f)->probing_parser_toclient_al_proto_masks = 0; \ if ((f)->de_state != NULL) { \ DetectEngineStateReset((f)->de_state); \ } \ diff --git a/src/flow.h b/src/flow.h index 25aa13b6b8..51d14dba55 100644 --- a/src/flow.h +++ b/src/flow.h @@ -174,6 +174,9 @@ typedef struct Flow_ */ SC_ATOMIC_DECLARE(unsigned short, use_cnt); + uint16_t probing_parser_toserver_al_proto_masks; + uint16_t probing_parser_toclient_al_proto_masks; + uint32_t flags; /* ts of flow init and last update */