summaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/app-layer-detect-proto.c
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:21:41 -0700
commit8879b125d26e8db1a5633de5a9c692eb2d1c4f83 (patch)
treec7259d85a991b83dfa85ab2e339360669fc1f58e /framework/src/suricata/src/app-layer-detect-proto.c
parent13d05bc8458758ee39cb829098241e89616717ee (diff)
suricata checkin based on commit id a4bce14770beee46a537eda3c3f6e8e8565d5d0a
Change-Id: I9a214fa0ee95e58fc640e50bd604dac7f42db48f
Diffstat (limited to 'framework/src/suricata/src/app-layer-detect-proto.c')
-rw-r--r--framework/src/suricata/src/app-layer-detect-proto.c3776
1 files changed, 3776 insertions, 0 deletions
diff --git a/framework/src/suricata/src/app-layer-detect-proto.c b/framework/src/suricata/src/app-layer-detect-proto.c
new file mode 100644
index 00000000..ed029e5e
--- /dev/null
+++ b/framework/src/suricata/src/app-layer-detect-proto.c
@@ -0,0 +1,3776 @@
+/* Copyright (C) 2007-2014 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ */
+
+#include "suricata-common.h"
+#include "debug.h"
+#include "decode.h"
+#include "threads.h"
+#include "threadvars.h"
+#include "tm-threads.h"
+
+#include "detect.h"
+#include "detect-engine-port.h"
+#include "detect-parse.h"
+#include "detect-engine.h"
+#include "detect-content.h"
+#include "detect-engine-mpm.h"
+#include "detect-engine-state.h"
+
+#include "util-print.h"
+#include "util-pool.h"
+#include "util-unittest.h"
+#include "util-unittest-helper.h"
+
+#include "flow.h"
+#include "flow-util.h"
+#include "flow-private.h"
+
+#include "stream-tcp-private.h"
+#include "stream-tcp-reassemble.h"
+#include "stream-tcp.h"
+#include "stream.h"
+
+#include "app-layer.h"
+#include "app-layer-protos.h"
+#include "app-layer-parser.h"
+#include "app-layer-detect-proto.h"
+
+#include "conf.h"
+#include "util-memcmp.h"
+#include "util-spm.h"
+#include "util-cuda.h"
+#include "util-debug.h"
+
+#include "runmodes.h"
+
+typedef struct AppLayerProtoDetectProbingParserElement_ {
+ AppProto alproto;
+ /* \todo don't really need it. See if you can get rid of it */
+ uint16_t port;
+ /* \todo calculate at runtime and get rid of this var */
+ uint32_t alproto_mask;
+ /* \todo check if we can reduce the bottom 2 vars to uint16_t */
+ /* 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 */
+ ProbingParserFPtr ProbingParser;
+
+ struct AppLayerProtoDetectProbingParserElement_ *next;
+} AppLayerProtoDetectProbingParserElement;
+
+typedef struct AppLayerProtoDetectProbingParserPort_ {
+ /* the port no for which probing parser(s) are invoked */
+ uint16_t port;
+
+ uint32_t alproto_mask;
+
+ /* the max depth for all the probing parsers registered for this port */
+ uint16_t dp_max_depth;
+ uint16_t sp_max_depth;
+
+ AppLayerProtoDetectProbingParserElement *dp;
+ AppLayerProtoDetectProbingParserElement *sp;
+
+ struct AppLayerProtoDetectProbingParserPort_ *next;
+} AppLayerProtoDetectProbingParserPort;
+
+typedef struct AppLayerProtoDetectProbingParser_ {
+ uint8_t ipproto;
+ AppLayerProtoDetectProbingParserPort *port;
+
+ struct AppLayerProtoDetectProbingParser_ *next;
+} AppLayerProtoDetectProbingParser;
+
+typedef struct AppLayerProtoDetectPMSignature_ {
+ AppProto alproto;
+ /* \todo Change this into a non-pointer */
+ DetectContentData *cd;
+ struct AppLayerProtoDetectPMSignature_ *next;
+} AppLayerProtoDetectPMSignature;
+
+typedef struct AppLayerProtoDetectPMCtx_ {
+ uint16_t max_len;
+ uint16_t min_len;
+ MpmCtx mpm_ctx;
+
+ /** Mapping between pattern id and signature. As each signature has a
+ * unique pattern with a unique id, we can lookup the signature by
+ * the pattern id. */
+ AppLayerProtoDetectPMSignature **map;
+ AppLayerProtoDetectPMSignature *head;
+
+ /* \todo we don't need this except at setup time. Get rid of it. */
+ PatIntId max_pat_id;
+} AppLayerProtoDetectPMCtx;
+
+typedef struct AppLayerProtoDetectCtxIpproto_ {
+ /* 0 - toserver, 1 - toclient */
+ AppLayerProtoDetectPMCtx ctx_pm[2];
+} AppLayerProtoDetectCtxIpproto;
+
+/**
+ * \brief The app layer protocol detection context.
+ */
+typedef struct AppLayerProtoDetectCtx_ {
+ /* Context per ip_proto.
+ * \todo Modify ctx_ipp to hold for only tcp and udp. The rest can be
+ * implemented if needed. Waste of space otherwise. */
+ AppLayerProtoDetectCtxIpproto ctx_ipp[FLOW_PROTO_DEFAULT];
+
+ AppLayerProtoDetectProbingParser *ctx_pp;
+
+ /* Indicates the protocols that have registered themselves
+ * for protocol detection. This table is independent of the
+ * ipproto. */
+ char *alproto_names[ALPROTO_MAX];
+} AppLayerProtoDetectCtx;
+
+/**
+ * \brief The app layer protocol detection thread context.
+ */
+struct AppLayerProtoDetectThreadCtx_ {
+ PatternMatcherQueue pmq;
+ /* The value 2 is for direction(0 - toserver, 1 - toclient). */
+ MpmThreadCtx mpm_tctx[FLOW_PROTO_DEFAULT][2];
+};
+
+/* The global app layer proto detection context. */
+static AppLayerProtoDetectCtx alpd_ctx;
+
+/***** Static Internal Calls: Protocol Retrieval *****/
+
+/** \internal
+ * \brief Handle SPM search for Signature */
+static AppProto AppLayerProtoDetectPMMatchSignature(const AppLayerProtoDetectPMSignature *s,
+ uint8_t *buf, uint16_t buflen,
+ uint8_t ipproto)
+{
+ SCEnter();
+ AppProto proto = ALPROTO_UNKNOWN;
+ uint8_t *found = NULL;
+
+ if (s->cd->offset > buflen) {
+ SCLogDebug("s->co->offset (%"PRIu16") > buflen (%"PRIu16")",
+ s->cd->offset, buflen);
+ goto end;
+ }
+
+ if (s->cd->depth > buflen) {
+ SCLogDebug("s->co->depth (%"PRIu16") > buflen (%"PRIu16")",
+ s->cd->depth, buflen);
+ goto end;
+ }
+
+ uint8_t *sbuf = buf + s->cd->offset;
+ uint16_t sbuflen = s->cd->depth - s->cd->offset;
+ SCLogDebug("s->co->offset (%"PRIu16") s->cd->depth (%"PRIu16")",
+ s->cd->offset, s->cd->depth);
+
+ if (s->cd->flags & DETECT_CONTENT_NOCASE)
+ found = BoyerMooreNocase(s->cd->content, s->cd->content_len, sbuf, sbuflen, s->cd->bm_ctx);
+ else
+ found = BoyerMoore(s->cd->content, s->cd->content_len, sbuf, sbuflen, s->cd->bm_ctx);
+ if (found != NULL)
+ proto = s->alproto;
+
+ end:
+ SCReturnUInt(proto);
+}
+
+/** \internal
+ * \brief Run Pattern Sigs against buffer
+ * \param pm_results[out] AppProto array of size ALPROTO_MAX */
+static AppProto AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx *tctx,
+ Flow *f,
+ uint8_t *buf, uint16_t buflen,
+ uint8_t direction,
+ uint8_t ipproto,
+ AppProto *pm_results)
+{
+ SCEnter();
+
+ pm_results[0] = ALPROTO_UNKNOWN;
+
+ AppLayerProtoDetectPMCtx *pm_ctx;
+ MpmThreadCtx *mpm_tctx;
+ uint16_t pm_matches = 0;
+ uint8_t cnt;
+ uint16_t searchlen;
+
+ if (f->protomap >= FLOW_PROTO_DEFAULT)
+ return ALPROTO_UNKNOWN;
+
+ if (direction & STREAM_TOSERVER) {
+ pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
+ mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
+ } else {
+ pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
+ mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
+ }
+ if (pm_ctx->mpm_ctx.pattern_cnt == 0)
+ goto end;
+
+ searchlen = buflen;
+ if (searchlen > pm_ctx->max_len)
+ searchlen = pm_ctx->max_len;
+
+ uint32_t search_cnt = 0;
+
+ /* do the mpm search */
+ search_cnt = mpm_table[pm_ctx->mpm_ctx.mpm_type].Search(&pm_ctx->mpm_ctx,
+ mpm_tctx,
+ &tctx->pmq,
+ buf, searchlen);
+ if (search_cnt == 0)
+ goto end;
+
+ /* alproto bit field */
+ uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
+ memset(pm_results_bf, 0, sizeof(pm_results_bf));
+
+ /* loop through unique pattern id's. Can't use search_cnt here,
+ * as that contains all matches, tctx->pmq.pattern_id_array_cnt
+ * contains only *unique* matches. */
+ for (cnt = 0; cnt < tctx->pmq.pattern_id_array_cnt; cnt++) {
+ const AppLayerProtoDetectPMSignature *s = pm_ctx->map[tctx->pmq.pattern_id_array[cnt]];
+ while (s != NULL) {
+ AppProto proto = AppLayerProtoDetectPMMatchSignature(s,
+ buf, searchlen, ipproto);
+
+ /* store each unique proto once */
+ if (proto != ALPROTO_UNKNOWN &&
+ !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
+ {
+ pm_results[pm_matches++] = proto;
+ pm_results_bf[proto / 8] |= 1 << (proto % 8);
+ }
+ s = s->next;
+ }
+ }
+
+ end:
+ PmqReset(&tctx->pmq);
+ if (buflen >= pm_ctx->max_len)
+ FLOW_SET_PM_DONE(f, direction);
+ SCReturnUInt(pm_matches);
+}
+
+static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
+ uint8_t ipproto,
+ uint16_t port)
+{
+ AppLayerProtoDetectProbingParserPort *pp_port = NULL;
+
+ while (pp != NULL) {
+ if (pp->ipproto == ipproto)
+ break;
+
+ pp = pp->next;
+ }
+
+ if (pp == NULL)
+ goto end;
+
+ pp_port = pp->port;
+ while (pp_port != NULL) {
+ if (pp_port->port == port || pp_port->port == 0) {
+ break;
+ }
+ pp_port = pp_port->next;
+ }
+
+ end:
+ SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
+}
+
+/**
+ * \brief Call the probing parser if it exists for this flow.
+ *
+ * First we check the flow's dp as it's most likely to match. If that didn't
+ * lead to a PP, we try the sp.
+ *
+ */
+static AppProto AppLayerProtoDetectPPGetProto(Flow *f,
+ uint8_t *buf, uint32_t buflen,
+ uint8_t ipproto, uint8_t direction)
+{
+ 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_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
+ alproto_masks = &f->probing_parser_toserver_alproto_masks;
+ 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);
+ }
+
+ 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);
+ }
+ } else {
+ /* first try the destination port */
+ pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
+ alproto_masks = &f->probing_parser_toclient_alproto_masks;
+ 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);
+ }
+
+ 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);
+
+ pe2 = pp_port_sp->sp;
+ } else {
+ SCLogDebug("toclient - No probing parser registered for source port %"PRIu16,
+ f->sp);
+ }
+ }
+
+ 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)) {
+ pe = pe->next;
+ continue;
+ }
+
+ 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;
+ }
+ pe = pe2;
+ while (pe != NULL) {
+ if ((buflen < pe->min_depth) ||
+ (alproto_masks[0] & pe->alproto_mask)) {
+ pe = pe->next;
+ continue;
+ }
+
+ 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->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;
+ 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 {
+ SCLogDebug("%s, mask is now %08x, need %08x",
+ (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0], mask);
+ }
+
+ end:
+ SCLogDebug("%s, mask is now %08x",
+ (direction & STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
+ SCReturnUInt(alproto);
+}
+
+/***** Static Internal Calls: PP registration *****/
+
+static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
+ uint8_t *ipprotos)
+{
+ SCEnter();
+
+ const AppLayerProtoDetectProbingParser *pp;
+ const AppLayerProtoDetectProbingParserPort *pp_port;
+ const AppLayerProtoDetectProbingParserElement *pp_pe;
+
+ for (pp = alpd_ctx.ctx_pp; pp != NULL; pp = pp->next) {
+ for (pp_port = pp->port; pp_port != NULL; pp_port = pp_port->next) {
+ for (pp_pe = pp_port->dp; pp_pe != NULL; pp_pe = pp_pe->next) {
+ if (alproto == pp_pe->alproto)
+ ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
+ }
+ for (pp_pe = pp_port->sp; pp_pe != NULL; pp_pe = pp_pe->next) {
+ if (alproto == pp_pe->alproto)
+ ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
+ }
+ }
+ }
+
+ SCReturn;
+}
+
+static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto)
+{
+ SCEnter();
+
+ if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) {
+ SCLogError(SC_ERR_ALPARSER, "Unknown protocol detected - %"PRIu16,
+ alproto);
+ exit(EXIT_FAILURE);
+ }
+
+ SCReturnUInt(1 << alproto);
+}
+
+static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParserElement *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserElement));
+ if (unlikely(p == NULL)) {
+ exit(EXIT_FAILURE);
+ }
+ memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
+
+ SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
+}
+
+
+static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
+{
+ SCEnter();
+ SCFree(p);
+ SCReturn;
+}
+
+static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParserPort *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParserPort));
+ if (unlikely(p == NULL)) {
+ exit(EXIT_FAILURE);
+ }
+ memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
+
+ SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
+}
+
+static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParserElement *e;
+
+ e = p->dp;
+ while (e != NULL) {
+ AppLayerProtoDetectProbingParserElement *e_next = e->next;
+ AppLayerProtoDetectProbingParserElementFree(e);
+ e = e_next;
+ }
+
+ e = p->sp;
+ while (e != NULL) {
+ AppLayerProtoDetectProbingParserElement *e_next = e->next;
+ AppLayerProtoDetectProbingParserElementFree(e);
+ e = e_next;
+ }
+
+ SCFree(p);
+
+ SCReturn;
+}
+
+static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParser *p = SCMalloc(sizeof(AppLayerProtoDetectProbingParser));
+ if (unlikely(p == NULL)) {
+ exit(EXIT_FAILURE);
+ }
+ memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
+
+ SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
+}
+
+static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParserPort *pt = p->port;
+ while (pt != NULL) {
+ AppLayerProtoDetectProbingParserPort *pt_next = pt->next;
+ AppLayerProtoDetectProbingParserPortFree(pt);
+ pt = pt_next;
+ }
+
+ SCFree(p);
+
+ SCReturn;
+}
+
+static AppLayerProtoDetectProbingParserElement *
+AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
+ uint16_t port,
+ uint16_t min_depth,
+ uint16_t max_depth,
+ uint16_t (*AppLayerProtoDetectProbingParser)
+ (uint8_t *input, uint32_t input_len, uint32_t *offset))
+{
+ AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
+
+ pe->alproto = alproto;
+ pe->port = port;
+ pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
+ pe->min_depth = min_depth;
+ pe->max_depth = max_depth;
+ pe->ProbingParser = AppLayerProtoDetectProbingParser;
+ pe->next = NULL;
+
+ if (max_depth != 0 && min_depth >= max_depth) {
+ SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
+ "register the probing parser. min_depth >= max_depth");
+ goto error;
+ }
+ if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
+ SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to register "
+ "the probing parser. Invalid alproto - %d", alproto);
+ goto error;
+ }
+ if (AppLayerProtoDetectProbingParser == NULL) {
+ SCLogError(SC_ERR_ALPARSER, "Invalid arguments sent to "
+ "register the probing parser. Probing parser func NULL");
+ goto error;
+ }
+
+ SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
+ error:
+ AppLayerProtoDetectProbingParserElementFree(pe);
+ SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
+}
+
+static AppLayerProtoDetectProbingParserElement *
+AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
+
+ new_pe->alproto = pe->alproto;
+ new_pe->port = pe->port;
+ new_pe->alproto_mask = pe->alproto_mask;
+ new_pe->min_depth = pe->min_depth;
+ new_pe->max_depth = pe->max_depth;
+ new_pe->ProbingParser = pe->ProbingParser;
+ new_pe->next = NULL;
+
+ SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
+}
+
+void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParserPort *pp_port = NULL;
+ AppLayerProtoDetectProbingParserElement *pp_pe = NULL;
+
+ printf("\nProtocol Detection Configuration\n");
+
+ for ( ; pp != NULL; pp = pp->next) {
+ /* print ip protocol */
+ if (pp->ipproto == IPPROTO_TCP)
+ printf("IPProto: TCP\n");
+ else if (pp->ipproto == IPPROTO_UDP)
+ printf("IPProto: UDP\n");
+ else
+ printf("IPProto: %"PRIu8"\n", pp->ipproto);
+
+ pp_port = pp->port;
+ for ( ; pp_port != NULL; pp_port = pp_port->next) {
+ if (pp_port->dp != NULL) {
+ printf(" Port: %"PRIu16 "\n", pp_port->port);
+
+ printf(" Destination port: (max-depth: %"PRIu16 ", "
+ "mask - %"PRIu32")\n",
+ pp_port->dp_max_depth,
+ pp_port->alproto_mask);
+ pp_pe = pp_port->dp;
+ for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
+
+ if (pp_pe->alproto == ALPROTO_HTTP)
+ printf(" alproto: ALPROTO_HTTP\n");
+ else if (pp_pe->alproto == ALPROTO_FTP)
+ printf(" alproto: ALPROTO_FTP\n");
+ else if (pp_pe->alproto == ALPROTO_SMTP)
+ printf(" alproto: ALPROTO_SMTP\n");
+ else if (pp_pe->alproto == ALPROTO_TLS)
+ printf(" alproto: ALPROTO_TLS\n");
+ else if (pp_pe->alproto == ALPROTO_SSH)
+ printf(" alproto: ALPROTO_SSH\n");
+ else if (pp_pe->alproto == ALPROTO_IMAP)
+ printf(" alproto: ALPROTO_IMAP\n");
+ else if (pp_pe->alproto == ALPROTO_MSN)
+ printf(" alproto: ALPROTO_MSN\n");
+ else if (pp_pe->alproto == ALPROTO_JABBER)
+ printf(" alproto: ALPROTO_JABBER\n");
+ else if (pp_pe->alproto == ALPROTO_SMB)
+ printf(" alproto: ALPROTO_SMB\n");
+ else if (pp_pe->alproto == ALPROTO_SMB2)
+ printf(" alproto: ALPROTO_SMB2\n");
+ else if (pp_pe->alproto == ALPROTO_DCERPC)
+ printf(" alproto: ALPROTO_DCERPC\n");
+ else if (pp_pe->alproto == ALPROTO_IRC)
+ printf(" alproto: ALPROTO_IRC\n");
+ else if (pp_pe->alproto == ALPROTO_DNS)
+ printf(" alproto: ALPROTO_DNS\n");
+ else if (pp_pe->alproto == ALPROTO_MODBUS)
+ printf(" alproto: ALPROTO_MODBUS\n");
+ else
+ printf("impossible\n");
+
+ printf(" port: %"PRIu16 "\n", pp_pe->port);
+ printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
+ printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
+ printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
+
+ printf("\n");
+ }
+ }
+
+ if (pp_port->sp == NULL) {
+ continue;
+ }
+
+ printf(" Source port: (max-depth: %"PRIu16 ", "
+ "mask - %"PRIu32")\n",
+ pp_port->sp_max_depth,
+ pp_port->alproto_mask);
+ pp_pe = pp_port->sp;
+ for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
+
+ if (pp_pe->alproto == ALPROTO_HTTP)
+ printf(" alproto: ALPROTO_HTTP\n");
+ else if (pp_pe->alproto == ALPROTO_FTP)
+ printf(" alproto: ALPROTO_FTP\n");
+ else if (pp_pe->alproto == ALPROTO_SMTP)
+ printf(" alproto: ALPROTO_SMTP\n");
+ else if (pp_pe->alproto == ALPROTO_TLS)
+ printf(" alproto: ALPROTO_TLS\n");
+ else if (pp_pe->alproto == ALPROTO_SSH)
+ printf(" alproto: ALPROTO_SSH\n");
+ else if (pp_pe->alproto == ALPROTO_IMAP)
+ printf(" alproto: ALPROTO_IMAP\n");
+ else if (pp_pe->alproto == ALPROTO_MSN)
+ printf(" alproto: ALPROTO_MSN\n");
+ else if (pp_pe->alproto == ALPROTO_JABBER)
+ printf(" alproto: ALPROTO_JABBER\n");
+ else if (pp_pe->alproto == ALPROTO_SMB)
+ printf(" alproto: ALPROTO_SMB\n");
+ else if (pp_pe->alproto == ALPROTO_SMB2)
+ printf(" alproto: ALPROTO_SMB2\n");
+ else if (pp_pe->alproto == ALPROTO_DCERPC)
+ printf(" alproto: ALPROTO_DCERPC\n");
+ else if (pp_pe->alproto == ALPROTO_IRC)
+ printf(" alproto: ALPROTO_IRC\n");
+ else if (pp_pe->alproto == ALPROTO_DNS)
+ printf(" alproto: ALPROTO_DNS\n");
+ else if (pp_pe->alproto == ALPROTO_MODBUS)
+ printf(" alproto: ALPROTO_MODBUS\n");
+ else
+ printf("impossible\n");
+
+ printf(" port: %"PRIu16 "\n", pp_pe->port);
+ printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
+ printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
+ printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
+
+ printf("\n");
+ }
+ }
+ }
+
+ SCReturn;
+}
+
+static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
+ AppLayerProtoDetectProbingParserElement *new_pe)
+{
+ SCEnter();
+
+ if (*head_pe == NULL) {
+ *head_pe = new_pe;
+ goto end;
+ }
+
+ if ((*head_pe)->port == 0) {
+ if (new_pe->port != 0) {
+ new_pe->next = *head_pe;
+ *head_pe = new_pe;
+ } else {
+ AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
+ while (temp_pe->next != NULL)
+ temp_pe = temp_pe->next;
+ temp_pe->next = new_pe;
+ }
+ } else {
+ AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
+ if (new_pe->port == 0) {
+ while (temp_pe->next != NULL)
+ temp_pe = temp_pe->next;
+ temp_pe->next = new_pe;
+ } else {
+ while (temp_pe->next != NULL && temp_pe->next->port != 0)
+ temp_pe = temp_pe->next;
+ new_pe->next = temp_pe->next;
+ temp_pe->next = new_pe;
+
+ }
+ }
+
+ end:
+ SCReturn;
+}
+
+static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
+ AppLayerProtoDetectProbingParser *new_pp)
+{
+ SCEnter();
+
+ if (*head_pp == NULL) {
+ *head_pp = new_pp;
+ goto end;
+ }
+
+ AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
+ while (temp_pp->next != NULL)
+ temp_pp = temp_pp->next;
+ temp_pp->next = new_pp;
+
+ end:
+ SCReturn;
+}
+
+static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
+ AppLayerProtoDetectProbingParserPort *new_port)
+{
+ SCEnter();
+
+ if (*head_port == NULL) {
+ *head_port = new_port;
+ goto end;
+ }
+
+ if ((*head_port)->port == 0) {
+ new_port->next = *head_port;
+ *head_port = new_port;
+ } else {
+ AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
+ while (temp_port->next != NULL && temp_port->next->port != 0) {
+ temp_port = temp_port->next;
+ }
+ new_port->next = temp_port->next;
+ temp_port->next = new_port;
+ }
+
+ end:
+ SCReturn;
+}
+
+static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
+ uint8_t ipproto,
+ uint16_t port,
+ AppProto alproto,
+ uint16_t min_depth, uint16_t max_depth,
+ uint8_t direction,
+ ProbingParserFPtr ProbingParser)
+{
+ SCEnter();
+
+ /* get the top level ipproto pp */
+ AppLayerProtoDetectProbingParser *curr_pp = *pp;
+ while (curr_pp != NULL) {
+ if (curr_pp->ipproto == ipproto)
+ break;
+ curr_pp = curr_pp->next;
+ }
+ if (curr_pp == NULL) {
+ AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
+ new_pp->ipproto = ipproto;
+ AppLayerProtoDetectProbingParserAppend(pp, new_pp);
+ curr_pp = new_pp;
+ }
+
+ /* get the top level port pp */
+ AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
+ while (curr_port != NULL) {
+ if (curr_port->port == port)
+ break;
+ curr_port = curr_port->next;
+ }
+ if (curr_port == NULL) {
+ AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
+ new_port->port = port;
+ AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
+ curr_port = new_port;
+ if (direction & STREAM_TOSERVER) {
+ curr_port->dp_max_depth = max_depth;
+ } else {
+ curr_port->sp_max_depth = max_depth;
+ }
+
+ AppLayerProtoDetectProbingParserPort *zero_port;
+
+ zero_port = curr_pp->port;
+ while (zero_port != NULL && zero_port->port != 0) {
+ zero_port = zero_port->next;
+ }
+ if (zero_port != NULL) {
+ AppLayerProtoDetectProbingParserElement *zero_pe;
+
+ zero_pe = zero_port->dp;
+ for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
+ if (curr_port->dp == NULL)
+ curr_port->dp_max_depth = zero_pe->max_depth;
+ if (zero_pe->max_depth == 0)
+ curr_port->dp_max_depth = zero_pe->max_depth;
+ if (curr_port->dp_max_depth != 0 &&
+ curr_port->dp_max_depth < zero_pe->max_depth) {
+ curr_port->dp_max_depth = zero_pe->max_depth;
+ }
+
+ AppLayerProtoDetectProbingParserElement *dup_pe =
+ AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
+ AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
+ curr_port->alproto_mask |= dup_pe->alproto_mask;
+ }
+
+ zero_pe = zero_port->sp;
+ for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
+ if (curr_port->sp == NULL)
+ curr_port->sp_max_depth = zero_pe->max_depth;
+ if (zero_pe->max_depth == 0)
+ curr_port->sp_max_depth = zero_pe->max_depth;
+ if (curr_port->sp_max_depth != 0 &&
+ curr_port->sp_max_depth < zero_pe->max_depth) {
+ curr_port->sp_max_depth = zero_pe->max_depth;
+ }
+
+ AppLayerProtoDetectProbingParserElement *dup_pe =
+ AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
+ AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
+ curr_port->alproto_mask |= dup_pe->alproto_mask;
+ }
+ } /* if (zero_port != NULL) */
+ } /* if (curr_port == NULL) */
+
+ /* insert the pe_pp */
+ AppLayerProtoDetectProbingParserElement *curr_pe;
+ if (direction & STREAM_TOSERVER)
+ curr_pe = curr_port->dp;
+ else
+ curr_pe = curr_port->sp;
+ while (curr_pe != NULL) {
+ if (curr_pe->alproto == alproto) {
+ SCLogError(SC_ERR_ALPARSER, "Duplicate pp registered - "
+ "ipproto - %"PRIu8" Port - %"PRIu16" "
+ "App Protocol - NULL, App Protocol(ID) - "
+ "%"PRIu16" min_depth - %"PRIu16" "
+ "max_dept - %"PRIu16".",
+ ipproto, port, alproto,
+ min_depth, max_depth);
+ goto error;
+ }
+ curr_pe = curr_pe->next;
+ }
+ /* Get a new parser element */
+ AppLayerProtoDetectProbingParserElement *new_pe =
+ AppLayerProtoDetectProbingParserElementCreate(alproto,
+ curr_port->port,
+ min_depth, max_depth,
+ ProbingParser);
+ if (new_pe == NULL)
+ goto error;
+ curr_pe = new_pe;
+ AppLayerProtoDetectProbingParserElement **head_pe;
+ if (direction & STREAM_TOSERVER) {
+ if (curr_port->dp == NULL)
+ curr_port->dp_max_depth = new_pe->max_depth;
+ if (new_pe->max_depth == 0)
+ curr_port->dp_max_depth = new_pe->max_depth;
+ if (curr_port->dp_max_depth != 0 &&
+ curr_port->dp_max_depth < new_pe->max_depth) {
+ curr_port->dp_max_depth = new_pe->max_depth;
+ }
+ curr_port->alproto_mask |= new_pe->alproto_mask;
+ head_pe = &curr_port->dp;
+ } else {
+ if (curr_port->sp == NULL)
+ curr_port->sp_max_depth = new_pe->max_depth;
+ if (new_pe->max_depth == 0)
+ curr_port->sp_max_depth = new_pe->max_depth;
+ if (curr_port->sp_max_depth != 0 &&
+ curr_port->sp_max_depth < new_pe->max_depth) {
+ curr_port->sp_max_depth = new_pe->max_depth;
+ }
+ curr_port->alproto_mask |= new_pe->alproto_mask;
+ head_pe = &curr_port->sp;
+ }
+ AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
+
+ if (curr_port->port == 0) {
+ AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
+ while (temp_port != NULL && temp_port->port != 0) {
+ if (direction & STREAM_TOSERVER) {
+ if (temp_port->dp == NULL)
+ temp_port->dp_max_depth = curr_pe->max_depth;
+ if (curr_pe->max_depth == 0)
+ temp_port->dp_max_depth = curr_pe->max_depth;
+ if (temp_port->dp_max_depth != 0 &&
+ temp_port->dp_max_depth < curr_pe->max_depth) {
+ temp_port->dp_max_depth = curr_pe->max_depth;
+ }
+ AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
+ AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
+ temp_port->alproto_mask |= curr_pe->alproto_mask;
+ } else {
+ if (temp_port->sp == NULL)
+ temp_port->sp_max_depth = curr_pe->max_depth;
+ if (curr_pe->max_depth == 0)
+ temp_port->sp_max_depth = curr_pe->max_depth;
+ if (temp_port->sp_max_depth != 0 &&
+ temp_port->sp_max_depth < curr_pe->max_depth) {
+ temp_port->sp_max_depth = curr_pe->max_depth;
+ }
+ AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
+ AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
+ temp_port->alproto_mask |= curr_pe->alproto_mask;
+ }
+ temp_port = temp_port->next;
+ } /* while */
+ } /* if */
+
+ error:
+ SCReturn;
+}
+
+/***** Static Internal Calls: PM registration *****/
+
+static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
+ uint8_t *ipprotos)
+{
+ SCEnter();
+
+ const AppLayerProtoDetectPMSignature *s = NULL;
+ int pat_id, max_pat_id;
+
+ int i, j;
+ uint8_t ipproto;
+
+ for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
+ ipproto = FlowGetReverseProtoMapping(i);
+ for (j = 0; j < 2; j++) {
+ AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
+ max_pat_id = pm_ctx->max_pat_id;
+
+ for (pat_id = 0; pat_id < max_pat_id; pat_id++) {
+ s = pm_ctx->map[pat_id];
+ while (s != NULL) {
+ if (s->alproto == alproto)
+ ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
+ s = s->next;
+ }
+ }
+ }
+ }
+
+ SCReturn;
+}
+
+static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
+{
+ SCEnter();
+
+ typedef struct TempContainer_ {
+ PatIntId id;
+ uint16_t content_len;
+ uint8_t *content;
+ } TempContainer;
+
+ AppLayerProtoDetectPMSignature *s = NULL;
+ uint32_t struct_total_size = 0;
+ uint32_t content_total_size = 0;
+ /* array hash buffer */
+ uint8_t *ahb = NULL;
+ uint8_t *content = NULL;
+ uint8_t content_len = 0;
+ PatIntId max_id = 0;
+ TempContainer *struct_offset = NULL;
+ uint8_t *content_offset = NULL;
+ TempContainer *dup = NULL;
+ int ret = 0;
+
+ if (ctx->head == NULL)
+ goto end;
+
+ for (s = ctx->head; s != NULL; s = s->next) {
+ struct_total_size += sizeof(TempContainer);
+ content_total_size += s->cd->content_len;
+ }
+
+ ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
+ if (unlikely(ahb == NULL))
+ goto error;
+
+ struct_offset = (TempContainer *)ahb;
+ content_offset = ahb + struct_total_size;
+ for (s = ctx->head; s != NULL; s = s->next) {
+ dup = (TempContainer *)ahb;
+ content = s->cd->content;
+ content_len = s->cd->content_len;
+
+ for (; dup != struct_offset; dup++) {
+ if (dup->content_len != content_len ||
+ SCMemcmp(dup->content, content, dup->content_len) != 0)
+ {
+ continue;
+ }
+ break;
+ }
+
+ if (dup != struct_offset) {
+ s->cd->id = dup->id;
+ continue;
+ }
+
+ struct_offset->content_len = content_len;
+ struct_offset->content = content_offset;
+ content_offset += content_len;
+ memcpy(struct_offset->content, content, content_len);
+ struct_offset->id = max_id++;
+ s->cd->id = struct_offset->id;
+
+ struct_offset++;
+ }
+
+ ctx->max_pat_id = max_id;
+
+ goto end;
+ error:
+ ret = -1;
+ end:
+ if (ahb != NULL)
+ SCFree(ahb);
+ SCReturnInt(ret);
+}
+
+static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
+{
+ SCEnter();
+
+ int ret = 0;
+ PatIntId max_pat_id = 0, tmp_pat_id;
+ AppLayerProtoDetectPMSignature *s, *next_s;
+ int mpm_ret;
+
+ max_pat_id = ctx->max_pat_id;
+
+ ctx->map = SCMalloc((max_pat_id) * sizeof(AppLayerProtoDetectPMSignature *));
+ if (ctx->map == NULL)
+ goto error;
+ memset(ctx->map, 0, (max_pat_id) * sizeof(AppLayerProtoDetectPMSignature *));
+
+ /* add an array indexed by pattern id to look up the sig */
+ for (s = ctx->head; s != NULL;) {
+ next_s = s->next;
+ s->next = ctx->map[s->cd->id];
+ ctx->map[s->cd->id] = s;
+ s = next_s;
+ }
+ ctx->head = NULL;
+
+
+ for (tmp_pat_id = 0; tmp_pat_id < max_pat_id; tmp_pat_id++) {
+ s = NULL;
+ for (s = ctx->map[tmp_pat_id]; s != NULL; s = s->next) {
+ if (s->cd->flags & DETECT_CONTENT_NOCASE) {
+ break;
+ }
+ }
+ /* if s != NULL now, it's CI. If NULL, CS */
+
+ if (s != NULL) {
+ mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
+ s->cd->content, s->cd->content_len,
+ 0, 0, tmp_pat_id, 0, 0);
+ if (mpm_ret < 0)
+ goto error;
+ } else {
+ s = ctx->map[tmp_pat_id];
+ if (s == NULL)
+ goto error;
+
+ mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
+ s->cd->content, s->cd->content_len,
+ 0, 0, tmp_pat_id, 0, 0);
+ if (mpm_ret < 0)
+ goto error;
+ }
+ }
+
+ goto end;
+ error:
+ ret = -1;
+ end:
+ SCReturnInt(ret);
+}
+
+static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
+{
+ SCEnter();
+
+ int ret = 0;
+ MpmCtx *mpm_ctx = &ctx->mpm_ctx;
+
+ if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
+ goto error;
+
+ goto end;
+ error:
+ ret = -1;
+ end:
+ SCReturnInt(ret);
+}
+
+static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
+{
+ SCEnter();
+ if (sig == NULL)
+ SCReturn;
+ if (sig->cd)
+ DetectContentFree(sig->cd);
+ SCFree(sig);
+ SCReturn;
+}
+
+static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
+ AppProto alproto)
+{
+ SCEnter();
+
+ int ret = 0;
+ AppLayerProtoDetectPMSignature *s = SCMalloc(sizeof(*s));
+ if (unlikely(s == NULL))
+ goto error;
+ memset(s, 0, sizeof(*s));
+
+ s->alproto = alproto;
+ s->cd = cd;
+
+ /* prepend to the list */
+ s->next = ctx->head;
+ ctx->head = s;
+
+ goto end;
+ error:
+ ret = -1;
+ end:
+ SCReturnInt(ret);
+}
+
+static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
+ char *pattern,
+ uint16_t depth, uint16_t offset,
+ uint8_t direction,
+ uint8_t is_cs)
+{
+ SCEnter();
+
+ AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
+ AppLayerProtoDetectPMCtx *ctx_pm = NULL;
+ DetectContentData *cd;
+ int ret = 0;
+
+ cd = DetectContentParseEncloseQuotes(pattern);
+ if (cd == NULL)
+ goto error;
+ cd->depth = depth;
+ cd->offset = offset;
+ if (!is_cs) {
+ BoyerMooreCtxToNocase(cd->bm_ctx, cd->content, cd->content_len);
+ cd->flags |= DETECT_CONTENT_NOCASE;
+ }
+ if (depth < cd->content_len)
+ goto error;
+
+ if (direction & STREAM_TOSERVER)
+ ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
+ else
+ ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
+
+ if (depth > ctx_pm->max_len)
+ ctx_pm->max_len = depth;
+ if (depth < ctx_pm->min_len)
+ ctx_pm->min_len = depth;
+
+ /* Finally turn it into a signature and add to the ctx. */
+ AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto);
+
+ goto end;
+ error:
+ ret = -1;
+ end:
+ SCReturnInt(ret);
+}
+
+/***** Protocol Retrieval *****/
+
+AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx,
+ Flow *f,
+ uint8_t *buf, uint32_t buflen,
+ uint8_t ipproto, uint8_t direction)
+{
+ SCEnter();
+
+ AppProto alproto = ALPROTO_UNKNOWN;
+ AppProto pm_results[ALPROTO_MAX];
+ uint16_t pm_matches;
+
+ if (!FLOW_IS_PM_DONE(f, direction)) {
+ pm_matches = AppLayerProtoDetectPMGetProto(tctx, f,
+ buf, buflen,
+ direction,
+ ipproto,
+ pm_results);
+ if (pm_matches > 0) {
+ alproto = pm_results[0];
+ goto end;
+ }
+ }
+
+ if (!FLOW_IS_PP_DONE(f, direction))
+ alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, direction);
+
+ end:
+ SCReturnCT(alproto, "AppProto");
+}
+
+static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
+{
+ SCEnter();
+
+ AppLayerProtoDetectProbingParser *tmp_pp = NULL;
+
+ if (pp == NULL)
+ goto end;
+
+ while (pp != NULL) {
+ tmp_pp = pp->next;
+ AppLayerProtoDetectProbingParserFree(pp);
+ pp = tmp_pp;
+ }
+
+ end:
+ SCReturn;
+}
+
+/***** State Preparation *****/
+
+int AppLayerProtoDetectPrepareState(void)
+{
+ SCEnter();
+
+ AppLayerProtoDetectPMCtx *ctx_pm;
+ int i, j;
+ int ret = 0;
+
+ for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
+ for (j = 0; j < 2; j++) {
+ ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
+
+ if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
+ goto error;
+
+ if (ctx_pm->max_pat_id == 0)
+ continue;
+
+ if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
+ goto error;
+ if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
+ goto error;
+ }
+ }
+
+#ifdef DEBUG
+ if (SCLogDebugEnabled()) {
+ AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
+ }
+#endif
+
+ goto end;
+ error:
+ ret = -1;
+ end:
+ SCReturnInt(ret);
+}
+
+/***** PP registration *****/
+
+/** \brief register parser at a port
+ *
+ * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
+ */
+void AppLayerProtoDetectPPRegister(uint8_t ipproto,
+ char *portstr,
+ AppProto alproto,
+ uint16_t min_depth, uint16_t max_depth,
+ uint8_t direction,
+ ProbingParserFPtr ProbingParser)
+{
+ SCEnter();
+
+ DetectPort *head = NULL;
+ DetectPortParse(NULL,&head, portstr);
+ DetectPort *temp_dp = head;
+ while (temp_dp != NULL) {
+ uint32_t port = temp_dp->port;
+ if (port == 0 && temp_dp->port2 != 0)
+ port++;
+ for ( ; port <= temp_dp->port2; port++) {
+ AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
+ ipproto,
+ port,
+ alproto,
+ min_depth, max_depth,
+ direction,
+ ProbingParser);
+ }
+ temp_dp = temp_dp->next;
+ }
+ DetectPortCleanupList(head);
+
+ SCReturn;
+}
+
+int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
+ uint8_t ipproto,
+ const char *alproto_name,
+ AppProto alproto,
+ uint16_t min_depth, uint16_t max_depth,
+ ProbingParserFPtr ProbingParser)
+{
+ SCEnter();
+
+ char param[100];
+ int r;
+ ConfNode *node;
+ ConfNode *port_node = NULL;
+ int config = 0;
+
+ r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
+ alproto_name, ".detection-ports");
+ if (r < 0) {
+ SCLogError(SC_ERR_FATAL, "snprintf failure.");
+ exit(EXIT_FAILURE);
+ } else if (r > (int)sizeof(param)) {
+ SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
+ exit(EXIT_FAILURE);
+ }
+ node = ConfGetNode(param);
+ if (node == NULL) {
+ SCLogDebug("Entry for %s not found.", param);
+ r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
+ alproto_name, ".", ipproto_name, ".detection-ports");
+ if (r < 0) {
+ SCLogError(SC_ERR_FATAL, "snprintf failure.");
+ exit(EXIT_FAILURE);
+ } else if (r > (int)sizeof(param)) {
+ SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
+ exit(EXIT_FAILURE);
+ }
+ node = ConfGetNode(param);
+ if (node == NULL)
+ goto end;
+ }
+
+ /* detect by destination port of the flow (e.g. port 53 for DNS) */
+ port_node = ConfNodeLookupChild(node, "dp");
+ if (port_node == NULL)
+ port_node = ConfNodeLookupChild(node, "toserver");
+
+ if (port_node != NULL && port_node->val != NULL) {
+ AppLayerProtoDetectPPRegister(ipproto,
+ port_node->val,
+ alproto,
+ min_depth, max_depth,
+ STREAM_TOSERVER, /* to indicate dp */
+ ProbingParser);
+ }
+
+ /* detect by source port of flow */
+ port_node = ConfNodeLookupChild(node, "sp");
+ if (port_node == NULL)
+ port_node = ConfNodeLookupChild(node, "toclient");
+
+ if (port_node != NULL && port_node->val != NULL) {
+ AppLayerProtoDetectPPRegister(ipproto,
+ port_node->val,
+ alproto,
+ min_depth, max_depth,
+ STREAM_TOCLIENT, /* to indicate sp */
+ ProbingParser);
+
+ }
+
+ config = 1;
+ end:
+ SCReturnInt(config);
+}
+
+/***** PM registration *****/
+
+int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto,
+ char *pattern,
+ uint16_t depth, uint16_t offset,
+ uint8_t direction)
+{
+ SCEnter();
+ int r = 0;
+ r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
+ pattern,
+ depth, offset,
+ direction,
+ 1 /* case-sensitive */);
+ SCReturnInt(r);
+}
+
+int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto,
+ char *pattern,
+ uint16_t depth, uint16_t offset,
+ uint8_t direction)
+{
+ SCEnter();
+ int r = 0;
+ r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
+ pattern,
+ depth, offset,
+ direction,
+ 0 /* !case-sensitive */);
+ SCReturnInt(r);
+}
+
+/***** Setup/General Registration *****/
+
+int AppLayerProtoDetectSetup(void)
+{
+ SCEnter();
+
+ int i, j;
+
+ memset(&alpd_ctx, 0, sizeof(alpd_ctx));
+
+ for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
+ for (j = 0; j < 2; j++) {
+ MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, MPM_AC);
+ }
+ }
+ SCReturnInt(0);
+}
+
+/**
+ * \todo incomplete. Need more work.
+ */
+int AppLayerProtoDetectDeSetup(void)
+{
+ SCEnter();
+
+ int ipproto_map = 0;
+ int dir = 0;
+ PatIntId id = 0;
+ AppLayerProtoDetectPMCtx *pm_ctx = NULL;
+ AppLayerProtoDetectPMSignature *sig = NULL, *next_sig = NULL;
+
+ for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
+ for (dir = 0; dir < 2; dir++) {
+ pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
+ mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(pm_ctx->mpm_ctx.ctx);
+ for (id = 0; id < pm_ctx->max_pat_id; id++) {
+ sig = pm_ctx->map[id];
+ while (sig != NULL) {
+ next_sig = sig->next;
+ AppLayerProtoDetectPMFreeSignature(sig);
+ sig = next_sig;
+ }
+ }
+ }
+ }
+
+ AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
+
+ SCReturnInt(0);
+}
+
+void AppLayerProtoDetectRegisterProtocol(AppProto alproto, char *alproto_name)
+{
+ SCEnter();
+
+ if (alpd_ctx.alproto_names[alproto] != NULL)
+ goto end;
+
+ alpd_ctx.alproto_names[alproto] = alproto_name;
+
+ goto end;
+ end:
+ SCReturn;
+}
+
+int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto,
+ const char *alproto)
+{
+ SCEnter();
+
+ BUG_ON(ipproto == NULL || alproto == NULL);
+
+ int enabled = 1;
+ char param[100];
+ ConfNode *node;
+ int r;
+
+ if (RunmodeIsUnittests())
+ goto enabled;
+
+ r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
+ alproto, ".enabled");
+ if (r < 0) {
+ SCLogError(SC_ERR_FATAL, "snprintf failure.");
+ exit(EXIT_FAILURE);
+ } else if (r > (int)sizeof(param)) {
+ SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
+ exit(EXIT_FAILURE);
+ }
+
+ node = ConfGetNode(param);
+ if (node == NULL) {
+ SCLogDebug("Entry for %s not found.", param);
+ r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
+ alproto, ".", ipproto, ".enabled");
+ if (r < 0) {
+ SCLogError(SC_ERR_FATAL, "snprintf failure.");
+ exit(EXIT_FAILURE);
+ } else if (r > (int)sizeof(param)) {
+ SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
+ exit(EXIT_FAILURE);
+ }
+
+ node = ConfGetNode(param);
+ if (node == NULL) {
+ SCLogDebug("Entry for %s not found.", param);
+ goto enabled;
+ }
+ }
+
+ if (node->val) {
+ if (ConfValIsTrue(node->val)) {
+ goto enabled;
+ } else if (ConfValIsFalse(node->val)) {
+ goto disabled;
+ } else if (strcasecmp(node->val, "detection-only") == 0) {
+ goto enabled;
+ }
+ }
+
+ /* Invalid or null value. */
+ SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
+ exit(EXIT_FAILURE);
+
+ disabled:
+ enabled = 0;
+ enabled:
+ SCReturnInt(enabled);
+}
+
+AppLayerProtoDetectThreadCtx *AppLayerProtoDetectGetCtxThread(void)
+{
+ SCEnter();
+
+ AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
+ MpmCtx *mpm_ctx;
+ MpmThreadCtx *mpm_tctx;
+ int i, j;
+ PatIntId max_pat_id = 0;
+
+ for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
+ for (j = 0; j < 2; j++) {
+ if (max_pat_id == 0) {
+ max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
+
+ } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
+ max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
+ {
+ max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
+ }
+ }
+ }
+
+ alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
+ if (alpd_tctx == NULL)
+ goto error;
+ memset(alpd_tctx, 0, sizeof(*alpd_tctx));
+
+ /* Get the max pat id for all the mpm ctxs. */
+ if (PmqSetup(&alpd_tctx->pmq, max_pat_id) < 0)
+ goto error;
+
+ for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
+ for (j = 0; j < 2; j++) {
+ mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
+ mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
+ mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx, 0);
+ }
+ }
+
+ goto end;
+ error:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ alpd_tctx = NULL;
+ end:
+ SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
+}
+
+void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
+{
+ SCEnter();
+
+ MpmCtx *mpm_ctx;
+ MpmThreadCtx *mpm_tctx;
+ int ipproto_map, dir;
+
+ for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
+ for (dir = 0; dir < 2; dir++) {
+ mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
+ mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
+ mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
+ }
+ }
+ PmqFree(&alpd_tctx->pmq);
+ SCFree(alpd_tctx);
+
+ SCReturn;
+}
+
+/***** Utility *****/
+
+void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
+{
+ SCEnter();
+
+ AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
+ AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
+
+ SCReturn;
+}
+
+AppProto AppLayerProtoDetectGetProtoByName(char *alproto_name)
+{
+ SCEnter();
+
+ AppProto a;
+ for (a = 0; a < ALPROTO_MAX; a++) {
+ if (alpd_ctx.alproto_names[a] != NULL &&
+ strlen(alpd_ctx.alproto_names[a]) == strlen(alproto_name) &&
+ (SCMemcmp(alpd_ctx.alproto_names[a], alproto_name, strlen(alproto_name)) == 0))
+ {
+ SCReturnCT(a, "AppProto");
+ }
+ }
+
+ SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
+}
+
+char *AppLayerProtoDetectGetProtoName(AppProto alproto)
+{
+ return alpd_ctx.alproto_names[alproto];
+}
+
+void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
+{
+ SCEnter();
+
+ memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
+
+ int alproto;
+
+ for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
+ if (alpd_ctx.alproto_names[alproto] != NULL)
+ alprotos[alproto] = 1;
+ }
+
+ SCReturn;
+}
+
+/***** Unittests *****/
+
+#ifdef UNITTESTS
+
+static AppLayerProtoDetectCtx alpd_ctx_ut;
+
+void AppLayerProtoDetectUnittestCtxBackup(void)
+{
+ SCEnter();
+ alpd_ctx_ut = alpd_ctx;
+ memset(&alpd_ctx, 0, sizeof(alpd_ctx));
+ SCReturn;
+}
+
+void AppLayerProtoDetectUnittestCtxRestore(void)
+{
+ SCEnter();
+ alpd_ctx = alpd_ctx_ut;
+ memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
+ SCReturn;
+}
+
+int AppLayerProtoDetectTest01(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ char *buf;
+ int r = 0;
+
+ buf = "HTTP";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
+ buf = "GET";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOSERVER);
+
+ AppLayerProtoDetectPrepareState();
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
+ printf("Failure - "
+ "alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("Failure - "
+ "alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest02(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ char *buf;
+ int r = 0;
+
+ buf = "HTTP";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
+ buf = "ftp";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest03(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "HTTP";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
+ buf = "220 ";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest04(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "200 ";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 13, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_HTTP\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest05(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "HTTP";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
+ buf = "220 ";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest06(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ buf = "HTTP";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
+ buf = "220 ";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_FTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_FTP\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1]->alproto != ALPROTO_HTTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[1].alproto != ALPROTO_HTTP\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_FTP) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_FTP\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest07(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "HTTP";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_HTTP\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 0) {
+ printf("cnt != 0\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest08(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = {
+ 0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
+ 0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
+ 0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
+ 0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
+ 0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
+ 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
+ 0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
+ 0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
+ 0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
+ 0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
+ 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
+ 0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
+ 0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
+ 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
+ 0x00
+ };
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "|ff|SMB";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_SMB) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_SMB\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_SMB) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_SMB\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest09(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = {
+ 0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x02
+ };
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "|fe|SMB";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB2, buf, 8, 4, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_SMB2) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_SMB2\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_SMB2) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_SMB2\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+int AppLayerProtoDetectTest10(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = {
+ 0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
+ 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+ 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+ 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
+ };
+ char *buf;
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ buf = "|05 00|";
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_DCERPC) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0].alproto != ALPROTO_DCERPC\n");
+ goto end;
+ }
+
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_DCERPC) {
+ printf("cnt != 1 && pm_results[0] != AlPROTO_DCERPC\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+/**
+ * \test Why we still get http for connect... obviously because
+ * we also match on the reply, duh
+ */
+int AppLayerProtoDetectTest11(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
+ uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ memset(pm_results, 0, sizeof(pm_results));
+
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map != NULL\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP)
+ {
+ printf("failure 1\n");
+ goto end;
+ }
+
+ memset(pm_results, 0, sizeof(pm_results));
+ uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOSERVER,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("l7data - cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
+ goto end;
+ }
+
+ memset(pm_results, 0, sizeof(pm_results));
+ cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data_resp, sizeof(l7data_resp),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("l7data_resp - cnt != 1 && pm_results[0] != AlPROTO_HTTP\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+/**
+ * \test AlpProtoSignature test
+ */
+int AppLayerProtoDetectTest12(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ int r = 0;
+
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
+ {
+ printf("failure 1\n");
+ goto end;
+ }
+
+ AppLayerProtoDetectPrepareState();
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
+ printf("failure 2\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
+ {
+ printf("failure 3\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
+ printf("failure 4\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
+ printf("failure 5\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
+ printf("failure 6\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+/**
+ * \test What about if we add some sigs only for udp but call for tcp?
+ * It should not detect any proto
+ */
+int AppLayerProtoDetectTest13(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
+ uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+ uint32_t cnt;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
+
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP)
+ {
+ printf("failure 1\n");
+ goto end;
+ }
+
+ memset(pm_results, 0, sizeof(pm_results));
+ cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOSERVER,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 0) {
+ printf("l7data - cnt != 0\n");
+ goto end;
+ }
+
+ memset(pm_results, 0, sizeof(pm_results));
+ cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data_resp, sizeof(l7data_resp),
+ STREAM_TOCLIENT,
+ IPPROTO_TCP,
+ pm_results);
+ if (cnt != 0) {
+ printf("l7data_resp - cnt != 0\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+/**
+ * \test What about if we add some sigs only for udp calling it for UDP?
+ * It should detect ALPROTO_HTTP (over udp). This is just a check
+ * to ensure that TCP/UDP differences work correctly.
+ */
+int AppLayerProtoDetectTest14(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
+ uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
+ int r = 0;
+ Flow f;
+ AppProto pm_results[ALPROTO_MAX];
+ AppLayerProtoDetectThreadCtx *alpd_tctx;
+ uint32_t cnt;
+
+ memset(&f, 0x00, sizeof(f));
+ f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
+
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
+ AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOCLIENT);
+
+ AppLayerProtoDetectPrepareState();
+ /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
+ * it sets internal structures which depends on the above function. */
+ alpd_tctx = AppLayerProtoDetectGetCtxThread();
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7\n");
+ goto end;
+ }
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1) {
+ printf("alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1\n");
+ goto end;
+ }
+
+ if (alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[1]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[2]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[3]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[4]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[5]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].map[6]->alproto != ALPROTO_HTTP ||
+ alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].map[0]->alproto != ALPROTO_HTTP)
+ {
+ printf("failure 1\n");
+ goto end;
+ }
+
+ memset(pm_results, 0, sizeof(pm_results));
+ cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data, sizeof(l7data),
+ STREAM_TOSERVER,
+ IPPROTO_UDP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("l7data - cnt != 0\n");
+ goto end;
+ }
+
+ memset(pm_results, 0, sizeof(pm_results));
+ cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
+ &f,
+ l7data_resp, sizeof(l7data_resp),
+ STREAM_TOCLIENT,
+ IPPROTO_UDP,
+ pm_results);
+ if (cnt != 1 && pm_results[0] != ALPROTO_HTTP) {
+ printf("l7data_resp - cnt != 0\n");
+ goto end;
+ }
+
+ r = 1;
+
+ end:
+ if (alpd_tctx != NULL)
+ AppLayerProtoDetectDestroyCtxThread(alpd_tctx);
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return r;
+}
+
+typedef struct AppLayerProtoDetectPPTestDataElement_ {
+ char *alproto_name;
+ AppProto alproto;
+ uint16_t port;
+ uint32_t alproto_mask;
+ uint32_t min_depth;
+ uint32_t max_depth;
+} AppLayerProtoDetectPPTestDataElement;
+
+typedef struct AppLayerProtoDetectPPTestDataPort_ {
+ uint16_t port;
+ uint32_t alproto_mask;
+ uint16_t dp_max_depth;
+ uint16_t sp_max_depth;
+
+ AppLayerProtoDetectPPTestDataElement *toserver_element;
+ AppLayerProtoDetectPPTestDataElement *toclient_element;
+ int ts_no_of_element;
+ int tc_no_of_element;
+} AppLayerProtoDetectPPTestDataPort;
+
+
+typedef struct AppLayerProtoDetectPPTestDataIPProto_ {
+ uint8_t ipproto;
+
+ AppLayerProtoDetectPPTestDataPort *port;
+ int no_of_port;
+} AppLayerProtoDetectPPTestDataIPProto;
+
+static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
+ AppLayerProtoDetectPPTestDataIPProto *ip_proto,
+ int no_of_ip_proto)
+{
+ int result = 0;
+ int i = -1, j = -1 , k = -1;
+#ifdef DEBUG
+ int dir = 0;
+#endif
+ for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
+ if (pp->ipproto != ip_proto[i].ipproto)
+ goto end;
+
+ AppLayerProtoDetectProbingParserPort *pp_port = pp->port;
+ for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
+ if (pp_port->port != ip_proto[i].port[k].port)
+ goto end;
+ if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
+ goto end;
+ if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
+ goto end;
+ if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
+ goto end;
+ if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
+ goto end;
+
+ AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
+#ifdef DEBUG
+ dir = 0;
+#endif
+ for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
+ j++, pp_element = pp_element->next) {
+
+ if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
+ goto end;
+ }
+ if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
+ goto end;
+ }
+ if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
+ goto end;
+ }
+ if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
+ goto end;
+ }
+ if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
+ goto end;
+ }
+ } /* for */
+ if (pp_element != NULL)
+ goto end;
+
+ pp_element = pp_port->sp;
+#ifdef DEBUG
+ dir = 1;
+#endif
+ for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
+ if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
+ goto end;
+ }
+ if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
+ goto end;
+ }
+ if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
+ goto end;
+ }
+ if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
+ goto end;
+ }
+ if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
+ goto end;
+ }
+ } /* for */
+ if (pp_element != NULL)
+ goto end;
+ }
+ if (pp_port != NULL)
+ goto end;
+ }
+ if (pp != NULL)
+ goto end;
+
+ result = 1;
+ end:
+#ifdef DEBUG
+ printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
+#endif
+ return result;
+}
+
+static uint16_t ProbingParserDummyForTesting(uint8_t *input,
+ uint32_t input_len,
+ uint32_t *offset)
+{
+ return 0;
+}
+
+static int AppLayerProtoDetectTest15(void)
+{
+ AppLayerProtoDetectUnittestCtxBackup();
+ AppLayerProtoDetectSetup();
+
+ int result = 0;
+
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "80",
+ ALPROTO_HTTP,
+ 5, 8,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "80",
+ ALPROTO_SMB,
+ 5, 6,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "80",
+ ALPROTO_FTP,
+ 7, 10,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "81",
+ ALPROTO_DCERPC,
+ 9, 10,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "81",
+ ALPROTO_FTP,
+ 7, 15,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "0",
+ ALPROTO_SMTP,
+ 12, 0,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "0",
+ ALPROTO_TLS,
+ 12, 18,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "85",
+ ALPROTO_DCERPC,
+ 9, 10,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "85",
+ ALPROTO_FTP,
+ 7, 15,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+ result = 1;
+
+ AppLayerProtoDetectPPRegister(IPPROTO_UDP,
+ "85",
+ ALPROTO_IMAP,
+ 12, 23,
+ STREAM_TOSERVER,
+ ProbingParserDummyForTesting);
+
+ /* toclient */
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "0",
+ ALPROTO_JABBER,
+ 12, 23,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "0",
+ ALPROTO_IRC,
+ 12, 14,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "85",
+ ALPROTO_DCERPC,
+ 9, 10,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "81",
+ ALPROTO_FTP,
+ 7, 15,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "0",
+ ALPROTO_TLS,
+ 12, 18,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "80",
+ ALPROTO_HTTP,
+ 5, 8,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "81",
+ ALPROTO_DCERPC,
+ 9, 10,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "90",
+ ALPROTO_FTP,
+ 7, 15,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "80",
+ ALPROTO_SMB,
+ 5, 6,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_UDP,
+ "85",
+ ALPROTO_IMAP,
+ 12, 23,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "0",
+ ALPROTO_SMTP,
+ 12, 17,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+ AppLayerProtoDetectPPRegister(IPPROTO_TCP,
+ "80",
+ ALPROTO_FTP,
+ 7, 10,
+ STREAM_TOCLIENT,
+ ProbingParserDummyForTesting);
+
+ AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
+ { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
+ { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
+ { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ };
+ AppLayerProtoDetectPPTestDataElement element_tc_80[] = {
+ { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
+ { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
+ { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
+ };
+
+ AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
+ { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
+ { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ };
+ AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
+ { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
+ { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
+ };
+
+ AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
+ { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
+ { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ };
+ AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
+ { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
+ };
+
+ AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ };
+ AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
+ { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
+ };
+
+ AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ };
+ AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
+ { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
+ { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
+ { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
+ { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
+ };
+
+
+ AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
+ { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
+ };
+ AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
+ { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
+ };
+
+ AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
+ { 80,
+ ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
+ (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
+ ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
+ (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
+ 23,
+ element_ts_80, element_tc_80,
+ sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ },
+ { 81,
+ ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
+ (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
+ ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) |
+ (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
+ 23,
+ element_ts_81, element_tc_81,
+ sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ },
+ { 85,
+ ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
+ (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
+ ((1 << ALPROTO_DCERPC) |
+ (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
+ 23,
+ element_ts_85, element_tc_85,
+ sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement)
+ },
+ { 90,
+ ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
+ ((1 << ALPROTO_FTP) |
+ (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
+ 23,
+ element_ts_90, element_tc_90,
+ sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement)
+ },
+ { 0,
+ ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
+ ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
+ 23,
+ element_ts_0, element_tc_0,
+ sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement)
+ }
+ };
+
+ AppLayerProtoDetectPPTestDataPort ports_udp[] = {
+ { 85,
+ (1 << ALPROTO_IMAP),
+ (1 << ALPROTO_IMAP),
+ 23,
+ element_ts_85_udp, element_tc_85_udp,
+ sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
+ },
+ };
+
+ AppLayerProtoDetectPPTestDataIPProto ip_proto[] = {
+ { IPPROTO_TCP,
+ ports_tcp,
+ sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
+ },
+ { IPPROTO_UDP,
+ ports_udp,
+ sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
+ },
+ };
+
+
+ if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
+ sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
+ goto end;
+ }
+ result = 1;
+
+ end:
+ AppLayerProtoDetectDeSetup();
+ AppLayerProtoDetectUnittestCtxRestore();
+ return result;
+}
+
+
+/** \test test if the engine detect the proto and match with it */
+static int AppLayerProtoDetectTest16(void)
+{
+ int result = 0;
+ Flow *f = NULL;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
+ if (p == NULL) {
+ printf("packet setup failed: ");
+ goto end;
+ }
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
+ if (f == NULL) {
+ printf("flow setup failed: ");
+ goto end;
+ }
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ p->flow = f;
+
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+
+ f->alproto = ALPROTO_HTTP;
+
+ StreamTcpInitConfig(TRUE);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->mpm_matcher = MPM_B2G;
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"Test content option\"; "
+ "sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ SCMutexLock(&f->m);
+ int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ SCMutexUnlock(&f->m);
+ goto end;
+ }
+ SCMutexUnlock(&f->m);
+
+ http_state = f->alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ if (!PacketAlertCheck(p, 1)) {
+ printf("sig 1 didn't alert, but it should: ");
+ goto end;
+ }
+ result = 1;
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(TRUE);
+
+ UTHFreePackets(&p, 1);
+ UTHFreeFlow(f);
+ return result;
+}
+
+/** \test test if the engine detect the proto on a non standar port
+ * and match with it */
+static int AppLayerProtoDetectTest17(void)
+{
+ int result = 0;
+ Flow *f = NULL;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
+ if (f == NULL)
+ goto end;
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ p->flow = f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f->alproto = ALPROTO_HTTP;
+
+ StreamTcpInitConfig(TRUE);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->mpm_matcher = MPM_B2G;
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
+ "(msg:\"http over non standar port\"; "
+ "sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ SCMutexLock(&f->m);
+ int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ SCMutexUnlock(&f->m);
+ goto end;
+ }
+ SCMutexUnlock(&f->m);
+
+ http_state = f->alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ if (!PacketAlertCheck(p, 1)) {
+ printf("sig 1 didn't alert, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(TRUE);
+
+ UTHFreePackets(&p, 1);
+ UTHFreeFlow(f);
+ return result;
+}
+
+/** \test test if the engine detect the proto and doesn't match
+ * because the sig expects another proto (ex ftp)*/
+static int AppLayerProtoDetectTest18(void)
+{
+ int result = 0;
+ Flow *f = NULL;
+ HtpState *http_state = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
+ if (f == NULL)
+ goto end;
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ p->flow = f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f->alproto = ALPROTO_HTTP;
+
+ StreamTcpInitConfig(TRUE);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->mpm_matcher = MPM_B2G;
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
+ "(msg:\"Test content option\"; "
+ "sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ SCMutexLock(&f->m);
+ int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ SCMutexUnlock(&f->m);
+ goto end;
+ }
+ SCMutexUnlock(&f->m);
+
+ http_state = f->alstate;
+ if (http_state == NULL) {
+ printf("no http state: ");
+ goto end;
+ }
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted, but it should not (it's not ftp): ");
+ goto end;
+ }
+
+ result = 1;
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(TRUE);
+
+ UTHFreePackets(&p, 1);
+ UTHFreeFlow(f);
+ return result;
+}
+
+/** \test test if the engine detect the proto and doesn't match
+ * because the packet has another proto (ex ftp) */
+static int AppLayerProtoDetectTest19(void)
+{
+ int result = 0;
+ Flow *f = NULL;
+ uint8_t http_buf1[] = "MPUT one\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
+ if (f == NULL)
+ goto end;
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ p->flow = f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f->alproto = ALPROTO_FTP;
+
+ StreamTcpInitConfig(TRUE);
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+ de_ctx->mpm_matcher = MPM_B2G;
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
+ "(msg:\"http over non standar port\"; "
+ "sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ SCMutexLock(&f->m);
+ int r = AppLayerParserParse(alp_tctx, f, ALPROTO_FTP, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ SCMutexUnlock(&f->m);
+ goto end;
+ }
+ SCMutexUnlock(&f->m);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ if (PacketAlertCheck(p, 1)) {
+ printf("sig 1 alerted, but it should not (it's ftp): ");
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(TRUE);
+ UTHFreePackets(&p, 1);
+ UTHFreeFlow(f);
+ return result;
+}
+
+/** \test test if the engine detect the proto and match with it
+ * and also against a content option */
+static int AppLayerProtoDetectTest20(void)
+{
+ int result = 0;
+ Flow *f = NULL;
+ uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
+ "User-Agent: Mozilla/1.0\r\n"
+ "Cookie: hellocatch\r\n\r\n";
+ uint32_t http_buf1_len = sizeof(http_buf1) - 1;
+ TcpSession ssn;
+ Packet *p = NULL;
+ Signature *s = NULL;
+ ThreadVars tv;
+ DetectEngineThreadCtx *det_ctx = NULL;
+ DetectEngineCtx *de_ctx = NULL;
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+ memset(&tv, 0, sizeof(ThreadVars));
+ memset(&ssn, 0, sizeof(TcpSession));
+
+ p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
+
+ f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
+ if (f == NULL)
+ goto end;
+ f->protoctx = &ssn;
+ p->flow = f;
+ p->flowflags |= FLOW_PKT_TOSERVER;
+ p->flowflags |= FLOW_PKT_ESTABLISHED;
+ p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
+ f->alproto = ALPROTO_HTTP;
+ f->proto = IPPROTO_TCP;
+ p->flags |= PKT_STREAM_ADD;
+ p->flags |= PKT_STREAM_EOF;
+
+ de_ctx = DetectEngineCtxInit();
+ if (de_ctx == NULL) {
+ goto end;
+ }
+
+ StreamTcpInitConfig(TRUE);
+
+ StreamMsg *stream_msg = StreamMsgGetFromPool();
+ if (stream_msg == NULL) {
+ printf("no stream_msg: ");
+ goto end;
+ }
+
+ memcpy(stream_msg->data, http_buf1, http_buf1_len);
+ stream_msg->data_len = http_buf1_len;
+
+ ssn.toserver_smsg_head = stream_msg;
+ ssn.toserver_smsg_tail = stream_msg;
+
+ de_ctx->mpm_matcher = MPM_B2G;
+ de_ctx->flags |= DE_QUIET;
+
+ s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
+ "(msg:\"Test content option\"; "
+ "content:\"one\"; sid:1;)");
+ if (s == NULL) {
+ goto end;
+ }
+
+ SigGroupBuild(de_ctx);
+ DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
+
+ SCMutexLock(&f->m);
+ int r = AppLayerParserParse(alp_tctx, f, ALPROTO_HTTP, STREAM_TOSERVER, http_buf1, http_buf1_len);
+ if (r != 0) {
+ printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+ SCMutexUnlock(&f->m);
+ goto end;
+ }
+ SCMutexUnlock(&f->m);
+
+ /* do detect */
+ SigMatchSignatures(&tv, de_ctx, det_ctx, p);
+
+ if (!PacketAlertCheck(p, 1)) {
+ printf("sig 1 didn't alert, but it should: ");
+ goto end;
+ }
+
+ result = 1;
+
+ end:
+ if (alp_tctx != NULL)
+ AppLayerParserThreadCtxFree(alp_tctx);
+ if (det_ctx != NULL)
+ DetectEngineThreadCtxDeinit(&tv, det_ctx);
+ if (de_ctx != NULL)
+ SigGroupCleanup(de_ctx);
+ if (de_ctx != NULL)
+ DetectEngineCtxFree(de_ctx);
+
+ StreamTcpFreeConfig(TRUE);
+ UTHFreePackets(&p, 1);
+ UTHFreeFlow(f);
+ return result;
+}
+
+
+void AppLayerProtoDetectUnittestsRegister(void)
+{
+ SCEnter();
+
+ UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01, 1);
+ UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02, 1);
+ UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03, 1);
+ UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04, 1);
+ UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05, 1);
+ UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06, 1);
+ UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07, 1);
+ UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08, 1);
+ UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09, 1);
+ UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10, 1);
+ UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11, 1);
+ UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12, 1);
+ UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13, 1);
+ UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14, 1);
+ UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15, 1);
+ UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16, 1);
+ UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17, 1);
+ UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18, 1);
+ UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19, 1);
+ UtRegisterTest("AppLayerProtoDetectTest20", AppLayerProtoDetectTest20, 1);
+
+ SCReturn;
+}
+
+#endif /* UNITTESTS */