suricata
app-layer-detect-proto.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23  */
24 
25 #include "suricata-common.h"
26 #include "decode.h"
27 #include "threads.h"
28 #include "threadvars.h"
29 #include "tm-threads.h"
30 
31 #include "detect.h"
32 #include "detect-engine-port.h"
33 #include "detect-engine-build.h"
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-content.h"
37 #include "detect-engine-mpm.h"
38 #include "detect-engine-state.h"
39 
40 #include "util-print.h"
41 #include "util-pool.h"
42 #include "util-unittest.h"
43 #include "util-unittest-helper.h"
44 #include "util-validate.h"
45 
46 #include "flow.h"
47 #include "flow-util.h"
48 #include "flow-private.h"
49 
50 #include "stream-tcp-private.h"
51 #include "stream-tcp-reassemble.h"
52 #include "stream-tcp.h"
53 #include "stream.h"
54 
55 #include "app-layer.h"
56 #include "app-layer-protos.h"
57 #include "app-layer-parser.h"
58 #include "app-layer-detect-proto.h"
59 #include "app-layer-expectation.h"
60 
61 #include "conf.h"
62 #include "util-memcmp.h"
63 #include "util-spm.h"
64 #include "util-debug.h"
65 
66 #include "runmodes.h"
67 
70  /* \todo don't really need it. See if you can get rid of it */
71  uint16_t port;
72  /* \todo calculate at runtime and get rid of this var */
73  uint32_t alproto_mask;
74  /* the min length of data that has to be supplied to invoke the parser */
75  uint16_t min_depth;
76  /* the max length of data after which this parser won't be invoked */
77  uint16_t max_depth;
78 
79  /* the to_server probing parser function */
81 
82  /* the to_client probing parser function */
84 
87 
89  /* the port no for which probing parser(s) are invoked */
90  uint16_t port;
91 
92  uint32_t alproto_mask;
93 
94  /* the max depth for all the probing parsers registered for this port */
95  uint16_t dp_max_depth;
96  uint16_t sp_max_depth;
97 
100 
103 
105  uint8_t ipproto;
107 
110 
113  uint8_t direction; /**< direction for midstream */
115  /* \todo Change this into a non-pointer */
117  uint16_t pp_min_depth;
118  uint16_t pp_max_depth;
122 
124  uint16_t pp_max_len;
125  uint16_t min_len;
127 
128  /** Mapping between pattern id and signature. As each signature has a
129  * unique pattern with a unique id, we can lookup the signature by
130  * the pattern id. */
133 
134  /* \todo we don't need this except at setup time. Get rid of it. */
138 
140  /* 0 - toserver, 1 - toclient */
143 
144 /**
145  * \brief The app layer protocol detection context.
146  */
147 typedef struct AppLayerProtoDetectCtx_ {
148  /* Context per ip_proto.
149  * \todo Modify ctx_ipp to hold for only tcp and udp. The rest can be
150  * implemented if needed. Waste of space otherwise. */
152 
153  /* Global SPM thread context prototype. */
155 
157 
158  /* Indicates the protocols that have registered themselves
159  * for protocol detection. This table is independent of the
160  * ipproto. */
163 
165  const char *proto_name;
166  const char *proto_alias;
169 
170 /**
171  * \brief The app layer protocol detection thread context.
172  */
175  /* The value 2 is for direction(0 - toserver, 1 - toclient). */
178 };
179 
180 /* The global app layer proto detection context. */
181 static AppLayerProtoDetectCtx alpd_ctx;
182 static AppLayerProtoDetectAliases *alpda_ctx = NULL;
183 
184 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
185  uint8_t *ipprotos);
186 
187 /***** Static Internal Calls: Protocol Retrieval *****/
188 
189 /** \internal
190  * \brief Handle SPM search for Signature
191  * \param buflen full size of the input buffer
192  * \param searchlen pattern matching portion of buffer */
193 static AppProto AppLayerProtoDetectPMMatchSignature(const AppLayerProtoDetectPMSignature *s,
194  AppLayerProtoDetectThreadCtx *tctx, Flow *f, uint8_t flags, const uint8_t *buf,
195  uint32_t buflen, uint16_t searchlen, bool *rflow)
196 {
197  SCEnter();
198 
199  if (s->cd->offset > searchlen) {
200  SCLogDebug("s->co->offset (%"PRIu16") > searchlen (%"PRIu16")",
201  s->cd->offset, searchlen);
203  }
204  if (s->cd->depth > searchlen) {
205  SCLogDebug("s->co->depth (%"PRIu16") > searchlen (%"PRIu16")",
206  s->cd->depth, searchlen);
208  }
209 
210  const uint8_t *sbuf = buf + s->cd->offset;
211  uint16_t ssearchlen = s->cd->depth - s->cd->offset;
212  SCLogDebug("s->co->offset (%"PRIu16") s->cd->depth (%"PRIu16")",
213  s->cd->offset, s->cd->depth);
214 
215  uint8_t *found = SpmScan(s->cd->spm_ctx, tctx->spm_thread_ctx,
216  sbuf, ssearchlen);
217  if (found == NULL) {
219  }
220 
221  uint8_t direction = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
222  SCLogDebug("matching, s->direction %s, our dir %s",
223  (s->direction & STREAM_TOSERVER) ? "toserver" : "toclient",
224  (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
225  if (s->PPFunc == NULL) {
226  if (direction == s->direction) {
227  SCLogDebug("direction is correct");
228  } else {
229  SCLogDebug("direction is wrong, rflow = true");
230  *rflow = true;
231  }
232  /* validate using Probing Parser */
233  } else {
234  if (s->pp_min_depth > buflen) {
235  SCLogDebug("PP can't be run yet as pp_min_depth %u > buflen %u",
236  s->pp_min_depth, buflen);
238  }
239 
240  uint8_t rdir = 0;
241  AppProto r = s->PPFunc(f, flags, buf, buflen, &rdir);
242  if (r == s->alproto) {
243  SCLogDebug("found %s/%u, rdir %02x reverse_flow? %s",
244  AppProtoToString(r), r, rdir,
245  (rdir && direction != rdir) ? "true" : "false");
246  *rflow = (rdir && direction != rdir);
247  SCReturnUInt(s->alproto);
248  } else if (r == ALPROTO_FAILED) {
250  } else {
251  /* unknown: lets see if we will try again later */
252  if (s->pp_max_depth < buflen) {
253  SCLogDebug("depth reached and answer inconclusive: fail");
255  }
257  }
258  }
259  SCReturnUInt(s->alproto);
260 }
261 
262 /**
263  * \retval 0 no matches
264  * \retval -1 no matches, mpm depth reached
265  */
266 static inline int PMGetProtoInspect(AppLayerProtoDetectThreadCtx *tctx,
267  AppLayerProtoDetectPMCtx *pm_ctx, MpmThreadCtx *mpm_tctx, Flow *f, const uint8_t *buf,
268  uint32_t buflen, uint8_t flags, AppProto *pm_results, bool *rflow)
269 {
270  int pm_matches = 0;
271 
272  // maxdepth is u16, so minimum is u16
273  uint16_t searchlen = (uint16_t)MIN(buflen, pm_ctx->mpm_ctx.maxdepth);
274  SCLogDebug("searchlen %u buflen %u", searchlen, buflen);
275 
276  /* do the mpm search */
277  uint32_t search_cnt = mpm_table[pm_ctx->mpm_ctx.mpm_type].Search(
278  &pm_ctx->mpm_ctx, mpm_tctx, &tctx->pmq,
279  buf, searchlen);
280  if (search_cnt == 0) {
281  if (buflen >= pm_ctx->mpm_ctx.maxdepth)
282  return -1;
283  return 0;
284  }
285 
286  /* alproto bit field */
287  uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1];
288  memset(pm_results_bf, 0, sizeof(pm_results_bf));
289 
290  /* loop through unique pattern id's. Can't use search_cnt here,
291  * as that contains all matches, tctx->pmq.pattern_id_array_cnt
292  * contains only *unique* matches. */
293  for (uint32_t cnt = 0; cnt < tctx->pmq.rule_id_array_cnt; cnt++) {
294  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[tctx->pmq.rule_id_array[cnt]];
295  while (s != NULL) {
296  AppProto proto = AppLayerProtoDetectPMMatchSignature(
297  s, tctx, f, flags, buf, buflen, searchlen, rflow);
298 
299  /* store each unique proto once */
300  if (AppProtoIsValid(proto) &&
301  !(pm_results_bf[proto / 8] & (1 << (proto % 8))) )
302  {
303  pm_results[pm_matches++] = proto;
304  pm_results_bf[proto / 8] |= 1 << (proto % 8);
305  }
306  s = s->next;
307  }
308  }
309  if (pm_matches == 0 && buflen >= pm_ctx->pp_max_len) {
310  pm_matches = -2;
311  }
312  PmqReset(&tctx->pmq);
313  return pm_matches;
314 }
315 
316 /** \internal
317  * \brief Run Pattern Sigs against buffer
318  * \param direction direction for the patterns
319  * \param pm_results[out] AppProto array of size ALPROTO_MAX */
320 static AppProto AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f,
321  const uint8_t *buf, uint32_t buflen, uint8_t flags, AppProto *pm_results, bool *rflow)
322 {
323  SCEnter();
324 
325  pm_results[0] = ALPROTO_UNKNOWN;
326 
327  AppLayerProtoDetectPMCtx *pm_ctx;
328  MpmThreadCtx *mpm_tctx;
329  int m = -1;
330 
331  if (f->protomap >= FLOW_PROTO_DEFAULT) {
332  pm_results[0] = ALPROTO_FAILED;
333  SCReturnUInt(1);
334  }
335 
336  if (flags & STREAM_TOSERVER) {
337  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
338  mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
339  } else {
340  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
341  mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
342  }
343  if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
344  m = PMGetProtoInspect(tctx, pm_ctx, mpm_tctx, f, buf, buflen, flags, pm_results, rflow);
345  }
346  /* pattern found, yay */
347  if (m > 0) {
349  SCReturnUInt((uint16_t)m);
350 
351  /* handle non-found in non-midstream case */
352  } else if (!stream_config.midstream) {
353  /* we can give up if mpm gave no results and its search depth
354  * was reached. */
355  if (m < 0) {
357  SCReturnUInt(0);
358  } else if (m == 0) {
359  SCReturnUInt(0);
360  }
361  SCReturnUInt((uint16_t)m);
362 
363  /* handle non-found in midstream case */
364  } else if (m <= 0) {
365  if (flags & STREAM_TOSERVER) {
366  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[1];
367  mpm_tctx = &tctx->mpm_tctx[f->protomap][1];
368  } else {
369  pm_ctx = &alpd_ctx.ctx_ipp[f->protomap].ctx_pm[0];
370  mpm_tctx = &tctx->mpm_tctx[f->protomap][0];
371  }
372  SCLogDebug("no matches and in midstream mode, lets try the "
373  "*patterns for the other side");
374 
375  int om = -1;
376  if (likely(pm_ctx->mpm_ctx.pattern_cnt > 0)) {
377  om = PMGetProtoInspect(
378  tctx, pm_ctx, mpm_tctx, f, buf, buflen, flags, pm_results, rflow);
379  }
380  /* found! */
381  if (om > 0) {
383  SCReturnUInt((uint16_t)om);
384 
385  /* both sides failed */
386  } else if (om < 0 && m && m < 0) {
388  SCReturnUInt(0);
389 
390  /* one side still uncertain */
391  } else if (om == 0 || m == 0) {
392  SCReturnUInt(0);
393  }
394  }
395  SCReturnUInt(0);
396 }
397 
398 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectGetProbingParser(
399  AppLayerProtoDetectProbingParser *pp, uint8_t ipproto, AppProto alproto)
400 {
402  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
403 
404  while (pp != NULL) {
405  if (pp->ipproto == ipproto)
406  break;
407  pp = pp->next;
408  }
409  if (pp == NULL)
410  return NULL;
411 
412  pp_port = pp->port;
413  while (pp_port != NULL) {
414  if (pp_port->dp != NULL && pp_port->dp->alproto == alproto) {
415  pp_elem = pp_port->dp;
416  break;
417  }
418  if (pp_port->sp != NULL && pp_port->sp->alproto == alproto) {
419  pp_elem = pp_port->sp;
420  break;
421  }
422  pp_port = pp_port->next;
423  }
424 
425  SCReturnPtr(pp_elem, "AppLayerProtoDetectProbingParserElement *");
426 }
427 
428 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectGetProbingParsers(AppLayerProtoDetectProbingParser *pp,
429  uint8_t ipproto,
430  uint16_t port)
431 {
432  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
433 
434  while (pp != NULL) {
435  if (pp->ipproto == ipproto)
436  break;
437 
438  pp = pp->next;
439  }
440 
441  if (pp == NULL)
442  goto end;
443 
444  pp_port = pp->port;
445  while (pp_port != NULL) {
446  if (pp_port->port == port || pp_port->port == 0) {
447  break;
448  }
449  pp_port = pp_port->next;
450  }
451 
452  end:
453  SCReturnPtr(pp_port, "AppLayerProtoDetectProbingParserPort *");
454 }
455 
456 
457 /**
458  * \brief Call the probing expectation to see if there is some for this flow.
459  *
460  */
461 static AppProto AppLayerProtoDetectPEGetProto(Flow *f, uint8_t ipproto, uint8_t flags)
462 {
463  AppProto alproto = ALPROTO_UNKNOWN;
464 
465  SCLogDebug("expectation check for %p (dir %d)", f, flags);
467 
468  alproto = AppLayerExpectationHandle(f, flags);
469 
470  return alproto;
471 }
472 
473 static inline AppProto PPGetProto(const AppLayerProtoDetectProbingParserElement *pe, Flow *f,
474  uint8_t flags, const uint8_t *buf, uint32_t buflen, uint32_t *alproto_masks, uint8_t *rdir)
475 {
476  while (pe != NULL) {
477  if ((buflen < pe->min_depth) ||
478  (alproto_masks[0] & pe->alproto_mask)) {
479  pe = pe->next;
480  continue;
481  }
482 
483  AppProto alproto = ALPROTO_UNKNOWN;
484  if (flags & STREAM_TOSERVER && pe->ProbingParserTs != NULL) {
485  alproto = pe->ProbingParserTs(f, flags, buf, buflen, rdir);
486  } else if (flags & STREAM_TOCLIENT && pe->ProbingParserTc != NULL) {
487  alproto = pe->ProbingParserTc(f, flags, buf, buflen, rdir);
488  }
489  if (AppProtoIsValid(alproto)) {
490  SCReturnUInt(alproto);
491  }
492  if (alproto == ALPROTO_FAILED ||
493  (pe->max_depth != 0 && buflen > pe->max_depth)) {
494  alproto_masks[0] |= pe->alproto_mask;
495  }
496  pe = pe->next;
497  }
498 
500 }
501 
502 /**
503  * \brief Call the probing parser if it exists for this flow.
504  *
505  * First we check the flow's dp as it's most likely to match. If that didn't
506  * lead to a PP, we try the sp.
507  *
508  */
509 static AppProto AppLayerProtoDetectPPGetProto(Flow *f, const uint8_t *buf, uint32_t buflen,
510  uint8_t ipproto, const uint8_t flags, bool *reverse_flow)
511 {
512  const AppLayerProtoDetectProbingParserPort *pp_port_dp = NULL;
513  const AppLayerProtoDetectProbingParserPort *pp_port_sp = NULL;
514  const AppLayerProtoDetectProbingParserElement *pe0 = NULL;
515  const AppLayerProtoDetectProbingParserElement *pe1 = NULL;
516  const AppLayerProtoDetectProbingParserElement *pe2 = NULL;
517  AppProto alproto = ALPROTO_UNKNOWN;
518  uint32_t *alproto_masks = NULL;
519  uint32_t mask = 0;
520  uint8_t idir = (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
521  uint8_t dir = idir;
522  uint16_t dp = f->protodetect_dp ? f->protodetect_dp : FLOW_GET_DP(f);
523  uint16_t sp = FLOW_GET_SP(f);
524  bool probe_is_found = false;
525 
526 again_midstream:
527  if (idir != dir) {
528  SWAP_VARS(uint16_t, dp, sp); /* look up parsers in rev dir */
529  }
530  SCLogDebug("%u->%u %s", sp, dp,
531  (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
532 
533  if (dir == STREAM_TOSERVER) {
534  /* first try the destination port */
535  pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
536  alproto_masks = &f->probing_parser_toserver_alproto_masks;
537  if (pp_port_dp != NULL) {
538  SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, dp);
539 
540  /* found based on destination port, so use dp registration */
541  pe1 = pp_port_dp->dp;
542  } else {
543  SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
544  }
545 
546  pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
547  if (pp_port_sp != NULL) {
548  SCLogDebug("toserver - Probing parser found for source port %"PRIu16, sp);
549 
550  /* found based on source port, so use sp registration */
551  pe2 = pp_port_sp->sp;
552  } else {
553  SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
554  }
555  } else {
556  /* first try the destination port */
557  pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
558  if (dir == idir) {
559  // do not update alproto_masks to let a chance to second packet
560  // for instance when sending a junk packet to a DNS server
561  alproto_masks = &f->probing_parser_toclient_alproto_masks;
562  }
563  if (pp_port_dp != NULL) {
564  SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, dp);
565 
566  /* found based on destination port, so use dp registration */
567  pe1 = pp_port_dp->dp;
568  } else {
569  SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
570  }
571 
572  pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
573  if (pp_port_sp != NULL) {
574  SCLogDebug("toclient - Probing parser found for source port %"PRIu16, sp);
575 
576  pe2 = pp_port_sp->sp;
577  } else {
578  SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
579  }
580  }
581 
582  if (dir == STREAM_TOSERVER && f->alproto_tc != ALPROTO_UNKNOWN) {
583  pe0 = AppLayerProtoDetectGetProbingParser(alpd_ctx.ctx_pp, ipproto, f->alproto_tc);
584  } else if (dir == STREAM_TOCLIENT && f->alproto_ts != ALPROTO_UNKNOWN) {
585  pe0 = AppLayerProtoDetectGetProbingParser(alpd_ctx.ctx_pp, ipproto, f->alproto_ts);
586  }
587 
588  if (pe1 == NULL && pe2 == NULL && pe0 == NULL) {
589  SCLogDebug("%s - No probing parsers found for either port",
590  (dir == STREAM_TOSERVER) ? "toserver":"toclient");
591  goto noparsers;
592  } else {
593  probe_is_found = true;
594  }
595 
596  /* run the parser(s): always call with original direction */
597  uint8_t rdir = 0;
598  alproto = PPGetProto(pe0, f, flags, buf, buflen, alproto_masks, &rdir);
599  if (AppProtoIsValid(alproto))
600  goto end;
601  alproto = PPGetProto(pe1, f, flags, buf, buflen, alproto_masks, &rdir);
602  if (AppProtoIsValid(alproto))
603  goto end;
604  alproto = PPGetProto(pe2, f, flags, buf, buflen, alproto_masks, &rdir);
605  if (AppProtoIsValid(alproto))
606  goto end;
607 
608  /* get the mask we need for this direction */
609  if (dir == idir) {
610  if (pp_port_dp && pp_port_sp)
611  mask = pp_port_dp->alproto_mask|pp_port_sp->alproto_mask;
612  else if (pp_port_dp)
613  mask = pp_port_dp->alproto_mask;
614  else if (pp_port_sp)
615  mask = pp_port_sp->alproto_mask;
616 
617  if (alproto_masks[0] == mask) {
618  FLOW_SET_PP_DONE(f, dir);
619  SCLogDebug("%s, mask is now %08x, needed %08x, so done",
620  (dir == STREAM_TOSERVER) ? "toserver":"toclient",
621  alproto_masks[0], mask);
622  } else {
623  SCLogDebug("%s, mask is now %08x, need %08x",
624  (dir == STREAM_TOSERVER) ? "toserver":"toclient",
625  alproto_masks[0], mask);
626  }
627  }
628 
629 noparsers:
630  if (stream_config.midstream && idir == dir) {
631  if (idir == STREAM_TOSERVER) {
632  dir = STREAM_TOCLIENT;
633  } else {
634  dir = STREAM_TOSERVER;
635  }
636  SCLogDebug("no match + midstream, retry the other direction %s",
637  (dir == STREAM_TOSERVER) ? "toserver" : "toclient");
638  goto again_midstream;
639  } else if (!probe_is_found) {
640  FLOW_SET_PP_DONE(f, idir);
641  }
642 
643  end:
644  if (AppProtoIsValid(alproto) && rdir != 0 && rdir != idir) {
645  SCLogDebug("PP found %u, is reverse flow", alproto);
646  *reverse_flow = true;
647  }
648 
649  SCLogDebug("%s, mask is now %08x",
650  (idir == STREAM_TOSERVER) ? "toserver":"toclient", alproto_masks[0]);
651  SCReturnUInt(alproto);
652 }
653 
654 /***** Static Internal Calls: PP registration *****/
655 
656 static void AppLayerProtoDetectPPGetIpprotos(AppProto alproto,
657  uint8_t *ipprotos)
658 {
659  SCEnter();
660 
664 
665  for (pp = alpd_ctx.ctx_pp; pp != NULL; pp = pp->next) {
666  for (pp_port = pp->port; pp_port != NULL; pp_port = pp_port->next) {
667  for (pp_pe = pp_port->dp; pp_pe != NULL; pp_pe = pp_pe->next) {
668  if (alproto == pp_pe->alproto)
669  ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
670  }
671  for (pp_pe = pp_port->sp; pp_pe != NULL; pp_pe = pp_pe->next) {
672  if (alproto == pp_pe->alproto)
673  ipprotos[pp->ipproto / 8] |= 1 << (pp->ipproto % 8);
674  }
675  }
676  }
677 
678  SCReturn;
679 }
680 
681 static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto)
682 {
683  SCEnter();
684 
685  if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) {
686  FatalError("Unknown protocol detected - %u", alproto);
687  }
688 
689  SCReturnUInt(1UL << (uint32_t)alproto);
690 }
691 
692 static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParserElementAlloc(void)
693 {
694  SCEnter();
695 
697  if (unlikely(p == NULL)) {
698  exit(EXIT_FAILURE);
699  }
700  memset(p, 0, sizeof(AppLayerProtoDetectProbingParserElement));
701 
702  SCReturnPtr(p, "AppLayerProtoDetectProbingParserElement");
703 }
704 
705 
706 static void AppLayerProtoDetectProbingParserElementFree(AppLayerProtoDetectProbingParserElement *p)
707 {
708  SCEnter();
709  SCFree(p);
710  SCReturn;
711 }
712 
713 static AppLayerProtoDetectProbingParserPort *AppLayerProtoDetectProbingParserPortAlloc(void)
714 {
715  SCEnter();
716 
718  if (unlikely(p == NULL)) {
719  exit(EXIT_FAILURE);
720  }
721  memset(p, 0, sizeof(AppLayerProtoDetectProbingParserPort));
722 
723  SCReturnPtr(p, "AppLayerProtoDetectProbingParserPort");
724 }
725 
726 static void AppLayerProtoDetectProbingParserPortFree(AppLayerProtoDetectProbingParserPort *p)
727 {
728  SCEnter();
729 
731 
732  e = p->dp;
733  while (e != NULL) {
735  AppLayerProtoDetectProbingParserElementFree(e);
736  e = e_next;
737  }
738 
739  e = p->sp;
740  while (e != NULL) {
742  AppLayerProtoDetectProbingParserElementFree(e);
743  e = e_next;
744  }
745 
746  SCFree(p);
747 
748  SCReturn;
749 }
750 
751 static AppLayerProtoDetectProbingParser *AppLayerProtoDetectProbingParserAlloc(void)
752 {
753  SCEnter();
754 
756  if (unlikely(p == NULL)) {
757  exit(EXIT_FAILURE);
758  }
759  memset(p, 0, sizeof(AppLayerProtoDetectProbingParser));
760 
761  SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
762 }
763 
764 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
765 {
766  SCEnter();
767 
769  while (pt != NULL) {
771  AppLayerProtoDetectProbingParserPortFree(pt);
772  pt = pt_next;
773  }
774 
775  SCFree(p);
776 
777  SCReturn;
778 }
779 
781 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
782  uint16_t port,
783  uint16_t min_depth,
784  uint16_t max_depth)
785 {
786  AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
787 
788  pe->alproto = alproto;
789  pe->port = port;
790  pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
791  pe->min_depth = min_depth;
792  pe->max_depth = max_depth;
793  pe->next = NULL;
794 
795  if (max_depth != 0 && min_depth >= max_depth) {
796  SCLogError("Invalid arguments sent to "
797  "register the probing parser. min_depth >= max_depth");
798  goto error;
799  }
800  if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
801  SCLogError("Invalid arguments sent to register "
802  "the probing parser. Invalid alproto - %d",
803  alproto);
804  goto error;
805  }
806 
807  SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
808  error:
809  AppLayerProtoDetectProbingParserElementFree(pe);
810  SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
811 }
812 
814 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
815 {
816  SCEnter();
817 
818  AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
819 
820  new_pe->alproto = pe->alproto;
821  new_pe->port = pe->port;
822  new_pe->alproto_mask = pe->alproto_mask;
823  new_pe->min_depth = pe->min_depth;
824  new_pe->max_depth = pe->max_depth;
825  new_pe->ProbingParserTs = pe->ProbingParserTs;
826  new_pe->ProbingParserTc = pe->ProbingParserTc;
827  new_pe->next = NULL;
828 
829  SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
830 }
831 
832 #ifdef DEBUG
833 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
834 {
835  SCEnter();
836 
837  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
839 
840  printf("\nProtocol Detection Configuration\n");
841 
842  for ( ; pp != NULL; pp = pp->next) {
843  /* print ip protocol */
844  if (pp->ipproto == IPPROTO_TCP)
845  printf("IPProto: TCP\n");
846  else if (pp->ipproto == IPPROTO_UDP)
847  printf("IPProto: UDP\n");
848  else
849  printf("IPProto: %"PRIu8"\n", pp->ipproto);
850 
851  pp_port = pp->port;
852  for ( ; pp_port != NULL; pp_port = pp_port->next) {
853  if (pp_port->dp != NULL) {
854  printf(" Port: %"PRIu16 "\n", pp_port->port);
855 
856  printf(" Destination port: (max-depth: %"PRIu16 ", "
857  "mask - %"PRIu32")\n",
858  pp_port->dp_max_depth,
859  pp_port->alproto_mask);
860  pp_pe = pp_port->dp;
861  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
862 
863  if (pp_pe->alproto == ALPROTO_HTTP1)
864  printf(" alproto: ALPROTO_HTTP1\n");
865  else if (pp_pe->alproto == ALPROTO_FTP)
866  printf(" alproto: ALPROTO_FTP\n");
867  else if (pp_pe->alproto == ALPROTO_FTPDATA)
868  printf(" alproto: ALPROTO_FTPDATA\n");
869  else if (pp_pe->alproto == ALPROTO_SMTP)
870  printf(" alproto: ALPROTO_SMTP\n");
871  else if (pp_pe->alproto == ALPROTO_TLS)
872  printf(" alproto: ALPROTO_TLS\n");
873  else if (pp_pe->alproto == ALPROTO_SSH)
874  printf(" alproto: ALPROTO_SSH\n");
875  else if (pp_pe->alproto == ALPROTO_IMAP)
876  printf(" alproto: ALPROTO_IMAP\n");
877  else if (pp_pe->alproto == ALPROTO_JABBER)
878  printf(" alproto: ALPROTO_JABBER\n");
879  else if (pp_pe->alproto == ALPROTO_SMB)
880  printf(" alproto: ALPROTO_SMB\n");
881  else if (pp_pe->alproto == ALPROTO_DCERPC)
882  printf(" alproto: ALPROTO_DCERPC\n");
883  else if (pp_pe->alproto == ALPROTO_IRC)
884  printf(" alproto: ALPROTO_IRC\n");
885  else if (pp_pe->alproto == ALPROTO_DNS)
886  printf(" alproto: ALPROTO_DNS\n");
887  else if (pp_pe->alproto == ALPROTO_MODBUS)
888  printf(" alproto: ALPROTO_MODBUS\n");
889  else if (pp_pe->alproto == ALPROTO_ENIP)
890  printf(" alproto: ALPROTO_ENIP\n");
891  else if (pp_pe->alproto == ALPROTO_NFS)
892  printf(" alproto: ALPROTO_NFS\n");
893  else if (pp_pe->alproto == ALPROTO_NTP)
894  printf(" alproto: ALPROTO_NTP\n");
895  else if (pp_pe->alproto == ALPROTO_TFTP)
896  printf(" alproto: ALPROTO_TFTP\n");
897  else if (pp_pe->alproto == ALPROTO_IKE)
898  printf(" alproto: ALPROTO_IKE\n");
899  else if (pp_pe->alproto == ALPROTO_KRB5)
900  printf(" alproto: ALPROTO_KRB5\n");
901  else if (pp_pe->alproto == ALPROTO_DHCP)
902  printf(" alproto: ALPROTO_DHCP\n");
903  else if (pp_pe->alproto == ALPROTO_QUIC)
904  printf(" alproto: ALPROTO_QUIC\n");
905  else if (pp_pe->alproto == ALPROTO_SNMP)
906  printf(" alproto: ALPROTO_SNMP\n");
907  else if (pp_pe->alproto == ALPROTO_SIP)
908  printf(" alproto: ALPROTO_SIP\n");
909  else if (pp_pe->alproto == ALPROTO_TEMPLATE)
910  printf(" alproto: ALPROTO_TEMPLATE\n");
911  else if (pp_pe->alproto == ALPROTO_RFB)
912  printf(" alproto: ALPROTO_RFB\n");
913  else if (pp_pe->alproto == ALPROTO_MQTT)
914  printf(" alproto: ALPROTO_MQTT\n");
915  else if (pp_pe->alproto == ALPROTO_PGSQL)
916  printf(" alproto: ALPROTO_PGSQL\n");
917  else if (pp_pe->alproto == ALPROTO_TELNET)
918  printf(" alproto: ALPROTO_TELNET\n");
919  else if (pp_pe->alproto == ALPROTO_DNP3)
920  printf(" alproto: ALPROTO_DNP3\n");
921  else if (pp_pe->alproto == ALPROTO_BITTORRENT_DHT)
922  printf(" alproto: ALPROTO_BITTORRENT_DHT\n");
923  else
924  printf("impossible\n");
925 
926  printf(" port: %"PRIu16 "\n", pp_pe->port);
927  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
928  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
929  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
930 
931  printf("\n");
932  }
933  }
934 
935  if (pp_port->sp == NULL) {
936  continue;
937  }
938 
939  printf(" Source port: (max-depth: %"PRIu16 ", "
940  "mask - %"PRIu32")\n",
941  pp_port->sp_max_depth,
942  pp_port->alproto_mask);
943  pp_pe = pp_port->sp;
944  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
945 
946  if (pp_pe->alproto == ALPROTO_HTTP1)
947  printf(" alproto: ALPROTO_HTTP1\n");
948  else if (pp_pe->alproto == ALPROTO_FTP)
949  printf(" alproto: ALPROTO_FTP\n");
950  else if (pp_pe->alproto == ALPROTO_FTPDATA)
951  printf(" alproto: ALPROTO_FTPDATA\n");
952  else if (pp_pe->alproto == ALPROTO_SMTP)
953  printf(" alproto: ALPROTO_SMTP\n");
954  else if (pp_pe->alproto == ALPROTO_TLS)
955  printf(" alproto: ALPROTO_TLS\n");
956  else if (pp_pe->alproto == ALPROTO_SSH)
957  printf(" alproto: ALPROTO_SSH\n");
958  else if (pp_pe->alproto == ALPROTO_IMAP)
959  printf(" alproto: ALPROTO_IMAP\n");
960  else if (pp_pe->alproto == ALPROTO_JABBER)
961  printf(" alproto: ALPROTO_JABBER\n");
962  else if (pp_pe->alproto == ALPROTO_SMB)
963  printf(" alproto: ALPROTO_SMB\n");
964  else if (pp_pe->alproto == ALPROTO_DCERPC)
965  printf(" alproto: ALPROTO_DCERPC\n");
966  else if (pp_pe->alproto == ALPROTO_IRC)
967  printf(" alproto: ALPROTO_IRC\n");
968  else if (pp_pe->alproto == ALPROTO_DNS)
969  printf(" alproto: ALPROTO_DNS\n");
970  else if (pp_pe->alproto == ALPROTO_MODBUS)
971  printf(" alproto: ALPROTO_MODBUS\n");
972  else if (pp_pe->alproto == ALPROTO_ENIP)
973  printf(" alproto: ALPROTO_ENIP\n");
974  else if (pp_pe->alproto == ALPROTO_NFS)
975  printf(" alproto: ALPROTO_NFS\n");
976  else if (pp_pe->alproto == ALPROTO_NTP)
977  printf(" alproto: ALPROTO_NTP\n");
978  else if (pp_pe->alproto == ALPROTO_TFTP)
979  printf(" alproto: ALPROTO_TFTP\n");
980  else if (pp_pe->alproto == ALPROTO_IKE)
981  printf(" alproto: ALPROTO_IKE\n");
982  else if (pp_pe->alproto == ALPROTO_KRB5)
983  printf(" alproto: ALPROTO_KRB5\n");
984  else if (pp_pe->alproto == ALPROTO_QUIC)
985  printf(" alproto: ALPROTO_QUIC\n");
986  else if (pp_pe->alproto == ALPROTO_DHCP)
987  printf(" alproto: ALPROTO_DHCP\n");
988  else if (pp_pe->alproto == ALPROTO_SNMP)
989  printf(" alproto: ALPROTO_SNMP\n");
990  else if (pp_pe->alproto == ALPROTO_SIP)
991  printf(" alproto: ALPROTO_SIP\n");
992  else if (pp_pe->alproto == ALPROTO_TEMPLATE)
993  printf(" alproto: ALPROTO_TEMPLATE\n");
994  else if (pp_pe->alproto == ALPROTO_RFB)
995  printf(" alproto: ALPROTO_RFB\n");
996  else if (pp_pe->alproto == ALPROTO_MQTT)
997  printf(" alproto: ALPROTO_MQTT\n");
998  else if (pp_pe->alproto == ALPROTO_PGSQL)
999  printf(" alproto: ALPROTO_PGSQL\n");
1000  else if (pp_pe->alproto == ALPROTO_TELNET)
1001  printf(" alproto: ALPROTO_TELNET\n");
1002  else if (pp_pe->alproto == ALPROTO_DNP3)
1003  printf(" alproto: ALPROTO_DNP3\n");
1004  else if (pp_pe->alproto == ALPROTO_BITTORRENT_DHT)
1005  printf(" alproto: ALPROTO_BITTORRENT_DHT\n");
1006  else
1007  printf("impossible\n");
1008 
1009  printf(" port: %"PRIu16 "\n", pp_pe->port);
1010  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
1011  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
1012  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
1013 
1014  printf("\n");
1015  }
1016  }
1017  }
1018 
1019  SCReturn;
1020 }
1021 #endif
1022 
1023 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
1025 {
1026  SCEnter();
1027 
1028  if (*head_pe == NULL) {
1029  *head_pe = new_pe;
1030  goto end;
1031  }
1032 
1033  if ((*head_pe)->port == 0) {
1034  if (new_pe->port != 0) {
1035  new_pe->next = *head_pe;
1036  *head_pe = new_pe;
1037  } else {
1038  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
1039  while (temp_pe->next != NULL)
1040  temp_pe = temp_pe->next;
1041  temp_pe->next = new_pe;
1042  }
1043  } else {
1044  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
1045  if (new_pe->port == 0) {
1046  while (temp_pe->next != NULL)
1047  temp_pe = temp_pe->next;
1048  temp_pe->next = new_pe;
1049  } else {
1050  while (temp_pe->next != NULL && temp_pe->next->port != 0)
1051  temp_pe = temp_pe->next;
1052  new_pe->next = temp_pe->next;
1053  temp_pe->next = new_pe;
1054 
1055  }
1056  }
1057 
1058  end:
1059  SCReturn;
1060 }
1061 
1062 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
1064 {
1065  SCEnter();
1066 
1067  if (*head_pp == NULL) {
1068  *head_pp = new_pp;
1069  goto end;
1070  }
1071 
1072  AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
1073  while (temp_pp->next != NULL)
1074  temp_pp = temp_pp->next;
1075  temp_pp->next = new_pp;
1076 
1077  end:
1078  SCReturn;
1079 }
1080 
1081 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
1083 {
1084  SCEnter();
1085 
1086  if (*head_port == NULL) {
1087  *head_port = new_port;
1088  goto end;
1089  }
1090 
1091  if ((*head_port)->port == 0) {
1092  new_port->next = *head_port;
1093  *head_port = new_port;
1094  } else {
1095  AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
1096  while (temp_port->next != NULL && temp_port->next->port != 0) {
1097  temp_port = temp_port->next;
1098  }
1099  new_port->next = temp_port->next;
1100  temp_port->next = new_port;
1101  }
1102 
1103  end:
1104  SCReturn;
1105 }
1106 
1107 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
1108  uint8_t ipproto,
1109  uint16_t port,
1110  AppProto alproto,
1111  uint16_t min_depth, uint16_t max_depth,
1112  uint8_t direction,
1113  ProbingParserFPtr ProbingParser1,
1114  ProbingParserFPtr ProbingParser2)
1115 {
1116  SCEnter();
1117 
1118  /* get the top level ipproto pp */
1119  AppLayerProtoDetectProbingParser *curr_pp = *pp;
1120  while (curr_pp != NULL) {
1121  if (curr_pp->ipproto == ipproto)
1122  break;
1123  curr_pp = curr_pp->next;
1124  }
1125  if (curr_pp == NULL) {
1126  AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1127  new_pp->ipproto = ipproto;
1128  AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1129  curr_pp = new_pp;
1130  }
1131 
1132  /* get the top level port pp */
1133  AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
1134  while (curr_port != NULL) {
1135  if (curr_port->port == port)
1136  break;
1137  curr_port = curr_port->next;
1138  }
1139  if (curr_port == NULL) {
1140  AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
1141  new_port->port = port;
1142  AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
1143  curr_port = new_port;
1144  if (direction & STREAM_TOSERVER) {
1145  curr_port->dp_max_depth = max_depth;
1146  } else {
1147  curr_port->sp_max_depth = max_depth;
1148  }
1149 
1151 
1152  zero_port = curr_pp->port;
1153  while (zero_port != NULL && zero_port->port != 0) {
1154  zero_port = zero_port->next;
1155  }
1156  if (zero_port != NULL) {
1158 
1159  zero_pe = zero_port->dp;
1160  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1161  if (curr_port->dp == NULL)
1162  curr_port->dp_max_depth = zero_pe->max_depth;
1163  if (zero_pe->max_depth == 0)
1164  curr_port->dp_max_depth = zero_pe->max_depth;
1165  if (curr_port->dp_max_depth != 0 &&
1166  curr_port->dp_max_depth < zero_pe->max_depth) {
1167  curr_port->dp_max_depth = zero_pe->max_depth;
1168  }
1169 
1171  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1172  AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1173  curr_port->alproto_mask |= dup_pe->alproto_mask;
1174  }
1175 
1176  zero_pe = zero_port->sp;
1177  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1178  if (curr_port->sp == NULL)
1179  curr_port->sp_max_depth = zero_pe->max_depth;
1180  if (zero_pe->max_depth == 0)
1181  curr_port->sp_max_depth = zero_pe->max_depth;
1182  if (curr_port->sp_max_depth != 0 &&
1183  curr_port->sp_max_depth < zero_pe->max_depth) {
1184  curr_port->sp_max_depth = zero_pe->max_depth;
1185  }
1186 
1188  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1189  AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1190  curr_port->alproto_mask |= dup_pe->alproto_mask;
1191  }
1192  } /* if (zero_port != NULL) */
1193  } /* if (curr_port == NULL) */
1194 
1195  /* insert the pe_pp */
1197  if (direction & STREAM_TOSERVER)
1198  curr_pe = curr_port->dp;
1199  else
1200  curr_pe = curr_port->sp;
1201  while (curr_pe != NULL) {
1202  if (curr_pe->alproto == alproto) {
1203  SCLogError("Duplicate pp registered - "
1204  "ipproto - %" PRIu8 " Port - %" PRIu16 " "
1205  "App Protocol - NULL, App Protocol(ID) - "
1206  "%" PRIu16 " min_depth - %" PRIu16 " "
1207  "max_dept - %" PRIu16 ".",
1208  ipproto, port, alproto, min_depth, max_depth);
1209  goto error;
1210  }
1211  curr_pe = curr_pe->next;
1212  }
1213  /* Get a new parser element */
1215  AppLayerProtoDetectProbingParserElementCreate(alproto,
1216  curr_port->port,
1217  min_depth, max_depth);
1218  if (new_pe == NULL)
1219  goto error;
1220  curr_pe = new_pe;
1222  if (direction & STREAM_TOSERVER) {
1223  curr_pe->ProbingParserTs = ProbingParser1;
1224  curr_pe->ProbingParserTc = ProbingParser2;
1225  if (curr_port->dp == NULL)
1226  curr_port->dp_max_depth = new_pe->max_depth;
1227  if (new_pe->max_depth == 0)
1228  curr_port->dp_max_depth = new_pe->max_depth;
1229  if (curr_port->dp_max_depth != 0 &&
1230  curr_port->dp_max_depth < new_pe->max_depth) {
1231  curr_port->dp_max_depth = new_pe->max_depth;
1232  }
1233  curr_port->alproto_mask |= new_pe->alproto_mask;
1234  head_pe = &curr_port->dp;
1235  } else {
1236  curr_pe->ProbingParserTs = ProbingParser2;
1237  curr_pe->ProbingParserTc = ProbingParser1;
1238  if (curr_port->sp == NULL)
1239  curr_port->sp_max_depth = new_pe->max_depth;
1240  if (new_pe->max_depth == 0)
1241  curr_port->sp_max_depth = new_pe->max_depth;
1242  if (curr_port->sp_max_depth != 0 &&
1243  curr_port->sp_max_depth < new_pe->max_depth) {
1244  curr_port->sp_max_depth = new_pe->max_depth;
1245  }
1246  curr_port->alproto_mask |= new_pe->alproto_mask;
1247  head_pe = &curr_port->sp;
1248  }
1249  AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1250 
1251  if (curr_port->port == 0) {
1252  AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
1253  while (temp_port != NULL && temp_port->port != 0) {
1254  if (direction & STREAM_TOSERVER) {
1255  if (temp_port->dp == NULL)
1256  temp_port->dp_max_depth = curr_pe->max_depth;
1257  if (curr_pe->max_depth == 0)
1258  temp_port->dp_max_depth = curr_pe->max_depth;
1259  if (temp_port->dp_max_depth != 0 &&
1260  temp_port->dp_max_depth < curr_pe->max_depth) {
1261  temp_port->dp_max_depth = curr_pe->max_depth;
1262  }
1263  AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1264  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1265  temp_port->alproto_mask |= curr_pe->alproto_mask;
1266  } else {
1267  if (temp_port->sp == NULL)
1268  temp_port->sp_max_depth = curr_pe->max_depth;
1269  if (curr_pe->max_depth == 0)
1270  temp_port->sp_max_depth = curr_pe->max_depth;
1271  if (temp_port->sp_max_depth != 0 &&
1272  temp_port->sp_max_depth < curr_pe->max_depth) {
1273  temp_port->sp_max_depth = curr_pe->max_depth;
1274  }
1275  AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1276  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1277  temp_port->alproto_mask |= curr_pe->alproto_mask;
1278  }
1279  temp_port = temp_port->next;
1280  } /* while */
1281  } /* if */
1282 
1283  error:
1284  SCReturn;
1285 }
1286 
1287 /***** Static Internal Calls: PM registration *****/
1288 
1289 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1290  uint8_t *ipprotos)
1291 {
1292  SCEnter();
1293 
1294  for (uint8_t i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1295  uint8_t ipproto = FlowGetReverseProtoMapping(i);
1296  for (int j = 0; j < 2; j++) {
1297  AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1298 
1299  for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1300  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1301  if (s->alproto == alproto)
1302  ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1303  }
1304  }
1305  }
1306 
1307  SCReturn;
1308 }
1309 
1310 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1311 {
1312  SCEnter();
1313 
1314  typedef struct TempContainer_ {
1315  PatIntId id;
1316  uint16_t content_len;
1317  uint8_t *content;
1318  } TempContainer;
1319 
1321  uint32_t struct_total_size = 0;
1322  uint32_t content_total_size = 0;
1323  /* array hash buffer */
1324  uint8_t *ahb = NULL;
1325  uint8_t *content = NULL;
1326  uint16_t content_len = 0;
1327  PatIntId max_id = 0;
1328  TempContainer *struct_offset = NULL;
1329  uint8_t *content_offset = NULL;
1330  int ret = 0;
1331 
1332  if (ctx->head == NULL)
1333  goto end;
1334 
1335  for (s = ctx->head; s != NULL; s = s->next) {
1336  struct_total_size += sizeof(TempContainer);
1337  content_total_size += s->cd->content_len;
1338  ctx->max_sig_id++;
1339  }
1340 
1341  ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1342  if (unlikely(ahb == NULL))
1343  goto error;
1344 
1345  struct_offset = (TempContainer *)ahb;
1346  content_offset = ahb + struct_total_size;
1347  for (s = ctx->head; s != NULL; s = s->next) {
1348  TempContainer *tcdup = (TempContainer *)ahb;
1349  content = s->cd->content;
1350  content_len = s->cd->content_len;
1351 
1352  for (; tcdup != struct_offset; tcdup++) {
1353  if (tcdup->content_len != content_len ||
1354  SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1355  {
1356  continue;
1357  }
1358  break;
1359  }
1360 
1361  if (tcdup != struct_offset) {
1362  s->cd->id = tcdup->id;
1363  continue;
1364  }
1365 
1366  struct_offset->content_len = content_len;
1367  struct_offset->content = content_offset;
1368  content_offset += content_len;
1369  memcpy(struct_offset->content, content, content_len);
1370  struct_offset->id = max_id++;
1371  s->cd->id = struct_offset->id;
1372 
1373  struct_offset++;
1374  }
1375 
1376  ctx->max_pat_id = max_id;
1377 
1378  goto end;
1379  error:
1380  ret = -1;
1381  end:
1382  if (ahb != NULL)
1383  SCFree(ahb);
1384  SCReturnInt(ret);
1385 }
1386 
1387 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1388 {
1389  SCEnter();
1390 
1391  int ret = 0;
1392  AppLayerProtoDetectPMSignature *s, *next_s;
1393  int mpm_ret;
1394  SigIntId id = 0;
1395 
1396  ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1397  if (ctx->map == NULL)
1398  goto error;
1399  memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1400 
1401  /* add an array indexed by rule id to look up the sig */
1402  for (s = ctx->head; s != NULL; ) {
1403  next_s = s->next;
1404  s->id = id++;
1405  SCLogDebug("s->id %u offset %u depth %u",
1406  s->id, s->cd->offset, s->cd->depth);
1407 
1408  if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1409  mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1410  s->cd->content, s->cd->content_len,
1411  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1412  if (mpm_ret < 0)
1413  goto error;
1414  } else {
1415  mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1416  s->cd->content, s->cd->content_len,
1417  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1418  if (mpm_ret < 0)
1419  goto error;
1420  }
1421 
1422  ctx->map[s->id] = s;
1423  s->next = NULL;
1424  s = next_s;
1425  }
1426  ctx->head = NULL;
1427 
1428  goto end;
1429  error:
1430  ret = -1;
1431  end:
1432  SCReturnInt(ret);
1433 }
1434 
1435 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1436 {
1437  SCEnter();
1438 
1439  int ret = 0;
1440  MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1441 
1442  if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1443  goto error;
1444 
1445  goto end;
1446  error:
1447  ret = -1;
1448  end:
1449  SCReturnInt(ret);
1450 }
1451 
1452 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1453 {
1454  SCEnter();
1455  if (sig == NULL)
1456  SCReturn;
1457  if (sig->cd)
1458  DetectContentFree(NULL, sig->cd);
1459  SCFree(sig);
1460  SCReturn;
1461 }
1462 
1463 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
1464  AppProto alproto, uint8_t direction,
1465  ProbingParserFPtr PPFunc,
1466  uint16_t pp_min_depth, uint16_t pp_max_depth)
1467 {
1468  SCEnter();
1469 
1470  AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1471  if (unlikely(s == NULL))
1472  SCReturnInt(-1);
1473 
1474  s->alproto = alproto;
1475  s->direction = direction;
1476  s->cd = cd;
1477  s->PPFunc = PPFunc;
1478  s->pp_min_depth = pp_min_depth;
1479  s->pp_max_depth = pp_max_depth;
1480 
1481  /* prepend to the list */
1482  s->next = ctx->head;
1483  ctx->head = s;
1484 
1485  SCReturnInt(0);
1486 }
1487 
1488 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1489  const char *pattern,
1490  uint16_t depth, uint16_t offset,
1491  uint8_t direction,
1492  uint8_t is_cs,
1493  ProbingParserFPtr PPFunc,
1494  uint16_t pp_min_depth, uint16_t pp_max_depth)
1495 {
1496  SCEnter();
1497 
1498  AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1499  AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1500  int ret = 0;
1501 
1503  alpd_ctx.spm_global_thread_ctx, pattern);
1504  if (cd == NULL)
1505  goto error;
1506  cd->depth = depth;
1507  cd->offset = offset;
1508  if (!is_cs) {
1509  /* Rebuild as nocase */
1510  SpmDestroyCtx(cd->spm_ctx);
1511  cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1512  alpd_ctx.spm_global_thread_ctx);
1513  if (cd->spm_ctx == NULL) {
1514  goto error;
1515  }
1517  }
1518  if (depth < cd->content_len)
1519  goto error;
1520 
1521  if (direction & STREAM_TOSERVER)
1522  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1523  else
1524  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1525 
1526  if (pp_max_depth > ctx_pm->pp_max_len)
1527  ctx_pm->pp_max_len = pp_max_depth;
1528  if (depth < ctx_pm->min_len)
1529  ctx_pm->min_len = depth;
1530 
1531  /* Finally turn it into a signature and add to the ctx. */
1532  AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1533  PPFunc, pp_min_depth, pp_max_depth);
1534 
1535  goto end;
1536  error:
1537  DetectContentFree(NULL, cd);
1538  ret = -1;
1539  end:
1540  SCReturnInt(ret);
1541 }
1542 
1543 /***** Protocol Retrieval *****/
1544 
1546  const uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t flags, bool *reverse_flow)
1547 {
1548  SCEnter();
1549  SCLogDebug("buflen %u for %s direction", buflen,
1550  (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1551 
1552  AppProto alproto = ALPROTO_UNKNOWN;
1553  AppProto pm_alproto = ALPROTO_UNKNOWN;
1554 
1555  if (!FLOW_IS_PM_DONE(f, flags)) {
1556  AppProto pm_results[ALPROTO_MAX];
1557  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(
1558  tctx, f, buf, buflen, flags, pm_results, reverse_flow);
1559  if (pm_matches > 0) {
1560  DEBUG_VALIDATE_BUG_ON(pm_matches > 1);
1561  alproto = pm_results[0];
1562 
1563  // rerun probing parser for other direction if it is unknown
1564  uint8_t reverse_dir = (flags & STREAM_TOSERVER) ? STREAM_TOCLIENT : STREAM_TOSERVER;
1565  if (FLOW_IS_PP_DONE(f, reverse_dir)) {
1566  AppProto rev_alproto = (flags & STREAM_TOSERVER) ? f->alproto_tc : f->alproto_ts;
1567  if (rev_alproto == ALPROTO_UNKNOWN) {
1568  FLOW_RESET_PP_DONE(f, reverse_dir);
1569  }
1570  }
1571 
1572  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1573  * to avoid misdetecting DNS as DCERPC. */
1574  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1575  goto end;
1576 
1577  pm_alproto = alproto;
1578 
1579  /* fall through */
1580  }
1581  }
1582 
1583  if (!FLOW_IS_PP_DONE(f, flags)) {
1584  bool rflow = false;
1585  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow);
1586  if (AppProtoIsValid(alproto)) {
1587  if (rflow) {
1588  *reverse_flow = true;
1589  }
1590  goto end;
1591  }
1592  }
1593 
1594  /* Look if flow can be found in expectation list */
1595  if (!FLOW_IS_PE_DONE(f, flags)) {
1596  alproto = AppLayerProtoDetectPEGetProto(f, ipproto, flags);
1597  }
1598 
1599  end:
1600  if (!AppProtoIsValid(alproto))
1601  alproto = pm_alproto;
1602 
1603  SCReturnUInt(alproto);
1604 }
1605 
1606 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1607 {
1608  SCEnter();
1609 
1610  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1611 
1612  if (pp == NULL)
1613  goto end;
1614 
1615  while (pp != NULL) {
1616  tmp_pp = pp->next;
1617  AppLayerProtoDetectProbingParserFree(pp);
1618  pp = tmp_pp;
1619  }
1620 
1621  end:
1622  SCReturn;
1623 }
1624 
1625 static void AppLayerProtoDetectFreeAliases(void)
1626 {
1627  SCEnter();
1628 
1629  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1630  if (cur_alias == NULL)
1631  goto end;
1632 
1633  AppLayerProtoDetectAliases *next_alias = NULL;
1634  while (cur_alias != NULL) {
1635  next_alias = cur_alias->next;
1636  SCFree(cur_alias);
1637  cur_alias = next_alias;
1638  }
1639 
1640  alpda_ctx = NULL;
1641 
1642 end:
1643  SCReturn;
1644 }
1645 
1646 /***** State Preparation *****/
1647 
1649 {
1650  SCEnter();
1651 
1652  AppLayerProtoDetectPMCtx *ctx_pm;
1653  int i, j;
1654  int ret = 0;
1655 
1656  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1657  for (j = 0; j < 2; j++) {
1658  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1659 
1660  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1661  goto error;
1662 
1663  if (ctx_pm->max_sig_id == 0)
1664  continue;
1665 
1666  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1667  goto error;
1668  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1669  goto error;
1670  }
1671  }
1672 
1673 #ifdef DEBUG
1674  if (SCLogDebugEnabled()) {
1675  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1676  }
1677 #endif
1678 
1679  goto end;
1680  error:
1681  ret = -1;
1682  end:
1683  SCReturnInt(ret);
1684 }
1685 
1686 /***** PP registration *****/
1687 
1688 /** \brief register parser at a port
1689  *
1690  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1691  */
1692 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1693  const char *portstr,
1694  AppProto alproto,
1695  uint16_t min_depth, uint16_t max_depth,
1696  uint8_t direction,
1697  ProbingParserFPtr ProbingParser1,
1698  ProbingParserFPtr ProbingParser2)
1699 {
1700  SCEnter();
1701 
1702  DetectPort *head = NULL;
1703  DetectPortParse(NULL,&head, portstr);
1704  DetectPort *temp_dp = head;
1705  while (temp_dp != NULL) {
1706  uint16_t port = temp_dp->port;
1707  if (port == 0 && temp_dp->port2 != 0)
1708  port++;
1709  for (;;) {
1710  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1711  ipproto,
1712  port,
1713  alproto,
1714  min_depth, max_depth,
1715  direction,
1716  ProbingParser1,
1717  ProbingParser2);
1718  if (port == temp_dp->port2) {
1719  break;
1720  } else {
1721  port++;
1722  }
1723  }
1724  temp_dp = temp_dp->next;
1725  }
1727 
1728  SCReturn;
1729 }
1730 
1731 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1732  uint8_t ipproto,
1733  const char *alproto_name,
1734  AppProto alproto,
1735  uint16_t min_depth, uint16_t max_depth,
1736  ProbingParserFPtr ProbingParserTs,
1737  ProbingParserFPtr ProbingParserTc)
1738 {
1739  SCEnter();
1740 
1741  char param[100];
1742  int r;
1743  ConfNode *node;
1744  ConfNode *port_node = NULL;
1745  int config = 0;
1746 
1747  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1748  alproto_name, ".detection-ports");
1749  if (r < 0) {
1750  FatalError("snprintf failure.");
1751  } else if (r > (int)sizeof(param)) {
1752  FatalError("buffer not big enough to write param.");
1753  }
1754  node = ConfGetNode(param);
1755  if (node == NULL) {
1756  SCLogDebug("Entry for %s not found.", param);
1757  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1758  alproto_name, ".", ipproto_name, ".detection-ports");
1759  if (r < 0) {
1760  FatalError("snprintf failure.");
1761  } else if (r > (int)sizeof(param)) {
1762  FatalError("buffer not big enough to write param.");
1763  }
1764  node = ConfGetNode(param);
1765  if (node == NULL)
1766  goto end;
1767  }
1768 
1769  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1770  port_node = ConfNodeLookupChild(node, "dp");
1771  if (port_node == NULL)
1772  port_node = ConfNodeLookupChild(node, "toserver");
1773 
1774  if (port_node != NULL && port_node->val != NULL) {
1776  port_node->val,
1777  alproto,
1778  min_depth, max_depth,
1779  STREAM_TOSERVER, /* to indicate dp */
1780  ProbingParserTs, ProbingParserTc);
1781  }
1782 
1783  /* detect by source port of flow */
1784  port_node = ConfNodeLookupChild(node, "sp");
1785  if (port_node == NULL)
1786  port_node = ConfNodeLookupChild(node, "toclient");
1787 
1788  if (port_node != NULL && port_node->val != NULL) {
1790  port_node->val,
1791  alproto,
1792  min_depth, max_depth,
1793  STREAM_TOCLIENT, /* to indicate sp */
1794  ProbingParserTc, ProbingParserTs);
1795 
1796  }
1797 
1798  config = 1;
1799  end:
1800  SCReturnInt(config);
1801 }
1802 
1803 /***** PM registration *****/
1804 
1806  const char *pattern,
1807  uint16_t depth, uint16_t offset,
1808  uint8_t direction)
1809 {
1810  SCEnter();
1811  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1812  pattern, depth, offset,
1813  direction, 1 /* case-sensitive */,
1814  NULL, 0, 0);
1815  SCReturnInt(r);
1816 }
1817 
1819  const char *pattern, uint16_t depth, uint16_t offset,
1820  uint8_t direction,
1821  ProbingParserFPtr PPFunc,
1822  uint16_t pp_min_depth, uint16_t pp_max_depth)
1823 {
1824  SCEnter();
1825  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1826  pattern, depth, offset,
1827  direction, 1 /* case-sensitive */,
1828  PPFunc, pp_min_depth, pp_max_depth);
1829  SCReturnInt(r);
1830 }
1831 
1833  const char *pattern,
1834  uint16_t depth, uint16_t offset,
1835  uint8_t direction)
1836 {
1837  SCEnter();
1838  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1839  pattern, depth, offset,
1840  direction, 0 /* !case-sensitive */,
1841  NULL, 0, 0);
1842  SCReturnInt(r);
1843 }
1844 
1845 /***** Setup/General Registration *****/
1846 
1848 {
1849  SCEnter();
1850 
1851  int i, j;
1852 
1853  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1854 
1855  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1856  uint8_t mpm_matcher = PatternMatchDefaultMatcher();
1857 
1858  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1859  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1860  FatalError("Unable to alloc SpmGlobalThreadCtx.");
1861  }
1862 
1863  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1864  for (j = 0; j < 2; j++) {
1865  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1866  }
1867  }
1868 
1870 
1871  SCReturnInt(0);
1872 }
1873 
1874 /**
1875  * \todo incomplete. Need more work.
1876  */
1878 {
1879  SCEnter();
1880 
1881  int ipproto_map = 0;
1882  int dir = 0;
1883  PatIntId id = 0;
1884  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1885  AppLayerProtoDetectPMSignature *sig = NULL;
1886 
1887  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1888  for (dir = 0; dir < 2; dir++) {
1889  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1890  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1891  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1892  sig = pm_ctx->map[id];
1893  AppLayerProtoDetectPMFreeSignature(sig);
1894  }
1895  SCFree(pm_ctx->map);
1896  pm_ctx->map = NULL;
1897  }
1898  }
1899 
1901 
1902  AppLayerProtoDetectFreeAliases();
1903 
1904  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1905 
1906  SCReturnInt(0);
1907 }
1908 
1909 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1910 {
1911  SCEnter();
1912 
1913  if (alpd_ctx.alproto_names[alproto] == NULL)
1914  alpd_ctx.alproto_names[alproto] = alproto_name;
1915 
1916  SCReturn;
1917 }
1918 
1919 void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
1920 {
1921  SCEnter();
1922 
1924  if (unlikely(new_alias == NULL)) {
1925  exit(EXIT_FAILURE);
1926  }
1927 
1928  new_alias->proto_name = proto_name;
1929  new_alias->proto_alias = proto_alias;
1930  new_alias->next = NULL;
1931 
1932  if (alpda_ctx == NULL) {
1933  alpda_ctx = new_alias;
1934  } else {
1935  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1936  while (cur_alias->next != NULL) {
1937  cur_alias = cur_alias->next;
1938  }
1939  cur_alias->next = new_alias;
1940  }
1941 
1942  SCReturn;
1943 }
1944 
1945 /** \brief request applayer to wrap up this protocol and rerun protocol
1946  * detection.
1947  *
1948  * When this is called, the old session is reset unconditionally. A
1949  * 'detect/log' flush packet is generated for both direction before
1950  * the reset, so allow for final detection and logging.
1951  *
1952  * \param f flow to act on
1953  * \param dp destination port to use in protocol detection. Set to 443
1954  * for start tls, set to the HTTP uri port for CONNECT and
1955  * set to 0 to not use it.
1956  * \param expect_proto expected protocol. AppLayer event will be set if
1957  * detected protocol differs from this.
1958  */
1959 bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1960 {
1961  if (FlowChangeProto(f)) {
1962  // If we are already changing protocols, from SMTP to TLS for instance,
1963  // and that we do not get TLS but HTTP1, which is requesting whange to HTTP2,
1964  // we do not proceed the new protocol change
1965  return false;
1966  }
1968  f->protodetect_dp = dp;
1969  f->alproto_expect = expect_proto;
1971  f->alproto_orig = f->alproto;
1972  // If one side is unknown yet, set it to the other known side
1973  if (f->alproto_ts == ALPROTO_UNKNOWN) {
1974  f->alproto_ts = f->alproto;
1975  }
1976  if (f->alproto_tc == ALPROTO_UNKNOWN) {
1977  f->alproto_tc = f->alproto;
1978  }
1979  return true;
1980 }
1981 
1982 /** \brief request applayer to wrap up this protocol and rerun protocol
1983  * detection with expectation of TLS. Used by STARTTLS.
1984  *
1985  * Sets detection port to 443 to make port based TLS detection work for
1986  * SMTP, FTP etc as well.
1987  *
1988  * \param f flow to act on
1989  */
1991 {
1993 }
1994 
1996 {
1997  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1998  FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1999  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
2000  FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
2001  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
2002  FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
2005 
2006  // Does not free the structures for the parser
2007  // keeps f->alstate for new state creation
2008  f->alparser = NULL;
2009  f->alproto = ALPROTO_UNKNOWN;
2012 }
2013 
2015  const char *ipproto, const char *alproto, bool default_enabled)
2016 {
2017  SCEnter();
2018 
2019  BUG_ON(ipproto == NULL || alproto == NULL);
2020 
2021  int enabled = 1;
2022  char param[100];
2023  ConfNode *node;
2024  int r;
2025 
2026  if (RunmodeIsUnittests())
2027  goto enabled;
2028 
2029  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
2030  alproto, ".enabled");
2031  if (r < 0) {
2032  FatalError("snprintf failure.");
2033  } else if (r > (int)sizeof(param)) {
2034  FatalError("buffer not big enough to write param.");
2035  }
2036 
2037  node = ConfGetNode(param);
2038  if (node == NULL) {
2039  SCLogDebug("Entry for %s not found.", param);
2040  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
2041  alproto, ".", ipproto, ".enabled");
2042  if (r < 0) {
2043  FatalError("snprintf failure.");
2044  } else if (r > (int)sizeof(param)) {
2045  FatalError("buffer not big enough to write param.");
2046  }
2047 
2048  node = ConfGetNode(param);
2049  if (node == NULL) {
2050  SCLogDebug("Entry for %s not found.", param);
2051  if (default_enabled) {
2052  goto enabled;
2053  } else {
2054  goto disabled;
2055  }
2056  }
2057  }
2058 
2059  if (node->val) {
2060  if (ConfValIsTrue(node->val)) {
2061  goto enabled;
2062  } else if (ConfValIsFalse(node->val)) {
2063  goto disabled;
2064  } else if (strcasecmp(node->val, "detection-only") == 0) {
2065  goto enabled;
2066  }
2067  }
2068 
2069  /* Invalid or null value. */
2070  SCLogError("Invalid value found for %s.", param);
2071  exit(EXIT_FAILURE);
2072 
2073  disabled:
2074  enabled = 0;
2075  enabled:
2076  SCReturnInt(enabled);
2077 }
2078 
2079 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
2080 {
2081  return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
2082 }
2083 
2085 {
2086  SCEnter();
2087 
2089  MpmCtx *mpm_ctx;
2090  MpmThreadCtx *mpm_tctx;
2091  int i, j;
2092  PatIntId max_pat_id = 0;
2093 
2094  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2095  for (j = 0; j < 2; j++) {
2096  if (max_pat_id == 0) {
2097  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2098 
2099  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
2100  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
2101  {
2102  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2103  }
2104  }
2105  }
2106 
2107  alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
2108  if (alpd_tctx == NULL)
2109  goto error;
2110  memset(alpd_tctx, 0, sizeof(*alpd_tctx));
2111 
2112  /* Get the max pat id for all the mpm ctxs. */
2113  if (PmqSetup(&alpd_tctx->pmq) < 0)
2114  goto error;
2115 
2116  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2117  for (j = 0; j < 2; j++) {
2118  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
2119  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
2120  mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
2121  }
2122  }
2123 
2125  if (alpd_tctx->spm_thread_ctx == NULL) {
2126  goto error;
2127  }
2128 
2129  goto end;
2130  error:
2131  if (alpd_tctx != NULL)
2133  alpd_tctx = NULL;
2134  end:
2135  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2136 }
2137 
2139 {
2140  SCEnter();
2141 
2142  MpmCtx *mpm_ctx;
2143  MpmThreadCtx *mpm_tctx;
2144  int ipproto_map, dir;
2145 
2146  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2147  for (dir = 0; dir < 2; dir++) {
2148  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2149  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2150  mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2151  }
2152  }
2153  PmqFree(&alpd_tctx->pmq);
2154  if (alpd_tctx->spm_thread_ctx != NULL) {
2156  }
2157  SCFree(alpd_tctx);
2158 
2159  SCReturn;
2160 }
2161 
2162 /***** Utility *****/
2163 
2164 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2165 {
2166  SCEnter();
2167 
2168  // Custom case for only signature-only protocol so far
2169  if (alproto == ALPROTO_HTTP) {
2172  } else {
2173  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2174  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2175  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2176  }
2177 
2178  SCReturn;
2179 }
2180 
2182 {
2183  SCEnter();
2184 
2185  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2186  while (cur_alias != NULL) {
2187  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2188  alproto_name = cur_alias->proto_name;
2189  }
2190 
2191  cur_alias = cur_alias->next;
2192  }
2193 
2194  AppProto a;
2195  AppProto b = StringToAppProto(alproto_name);
2196  for (a = 0; a < ALPROTO_MAX; a++) {
2197  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2198  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2199  SCReturnCT(b, "AppProto");
2200  }
2201  }
2202 
2203  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2204 }
2205 
2207 {
2208  // Special case for http (any version) :
2209  // returns "http" if both versions are enabled
2210  // and returns "http1" or "http2" if only one version is enabled
2211  if (alproto == ALPROTO_HTTP) {
2212  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2213  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2214  return "http";
2215  } // else
2216  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2217  } // else
2218  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2219  }
2220  return alpd_ctx.alproto_names[alproto];
2221 }
2222 
2224 {
2225  SCEnter();
2226 
2227  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2228 
2229  int alproto;
2230 
2231  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2232  if (alpd_ctx.alproto_names[alproto] != NULL)
2233  alprotos[alproto] = 1;
2234  }
2235 
2236  SCReturn;
2237 }
2238 
2240 
2241 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2242  uint8_t *ipprotos)
2243 {
2244  if (expectation_proto[alproto] == IPPROTO_TCP) {
2245  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2246  }
2247  if (expectation_proto[alproto] == IPPROTO_UDP) {
2248  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2249  }
2250 }
2251 
2253 {
2254  if (expectation_proto[alproto]) {
2255  if (proto != expectation_proto[alproto]) {
2256  SCLogError("Expectation on 2 IP protocols are not supported");
2257  }
2258  }
2259  expectation_proto[alproto] = proto;
2260 }
2261 
2262 /***** Unittests *****/
2263 
2264 #ifdef UNITTESTS
2265 
2266 #include "app-layer-htp.h"
2267 #include "detect-engine-alert.h"
2268 
2269 static AppLayerProtoDetectCtx alpd_ctx_ut;
2270 
2272 {
2273  SCEnter();
2274  alpd_ctx_ut = alpd_ctx;
2275  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2276  SCReturn;
2277 }
2278 
2280 {
2281  SCEnter();
2282  alpd_ctx = alpd_ctx_ut;
2283  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2284  SCReturn;
2285 }
2286 
2287 static int AppLayerProtoDetectTest01(void)
2288 {
2291 
2292  const char *buf = "HTTP";
2293  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2294  buf = "GET";
2295  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2296 
2298  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2299  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2300 
2303  PASS;
2304 }
2305 
2306 static int AppLayerProtoDetectTest02(void)
2307 {
2310 
2311  const char *buf = "HTTP";
2312  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2313  buf = "ftp";
2314  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2315 
2317  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2318  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2319 
2320  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2321  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2322 
2325 
2328  PASS;
2329 }
2330 
2331 static int AppLayerProtoDetectTest03(void)
2332 {
2335 
2336  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2337  AppProto pm_results[ALPROTO_MAX];
2338  memset(pm_results, 0, sizeof(pm_results));
2339  Flow f;
2340  memset(&f, 0x00, sizeof(f));
2341  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2342 
2343 
2344  const char *buf = "HTTP";
2345  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2346  buf = "220 ";
2347  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2348 
2350  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2351  * it sets internal structures which depends on the above function. */
2354 
2355  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2356  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2357  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2358  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2361 
2362  bool rflow = false;
2363  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2364  &f, l7data, sizeof(l7data),
2365  STREAM_TOCLIENT,
2366  pm_results, &rflow);
2367  FAIL_IF(cnt != 1);
2368  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2369 
2373  PASS;
2374 }
2375 
2376 static int AppLayerProtoDetectTest04(void)
2377 {
2380 
2381  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2382  Flow f;
2383  memset(&f, 0x00, sizeof(f));
2384  AppProto pm_results[ALPROTO_MAX];
2385  memset(pm_results, 0, sizeof(pm_results));
2386  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2387 
2388  const char *buf = "200 ";
2389  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2390 
2392  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2393  * it sets internal structures which depends on the above function. */
2396 
2397  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2398  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2399  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2400  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2402 
2403  bool rdir = false;
2404  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2405  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2406  pm_results, &rdir);
2407  FAIL_IF(cnt != 1);
2408  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2409 
2413  PASS;
2414 }
2415 
2416 static int AppLayerProtoDetectTest05(void)
2417 {
2420 
2421  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2422  AppProto pm_results[ALPROTO_MAX];
2423  memset(pm_results, 0, sizeof(pm_results));
2424  Flow f;
2425  memset(&f, 0x00, sizeof(f));
2426  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2427 
2428  const char *buf = "HTTP";
2429  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2430  buf = "220 ";
2431  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2432 
2434  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2435  * it sets internal structures which depends on the above function. */
2438 
2439  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2440  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2441  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2442  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2445 
2446  bool rdir = false;
2447  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2448  &f, l7data, sizeof(l7data),
2449  STREAM_TOCLIENT,
2450  pm_results, &rdir);
2451  FAIL_IF(cnt != 1);
2452  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2453 
2457  PASS;
2458 }
2459 
2460 static int AppLayerProtoDetectTest06(void)
2461 {
2464 
2465  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2466  AppProto pm_results[ALPROTO_MAX];
2467  memset(pm_results, 0, sizeof(pm_results));
2468  Flow f;
2469  memset(&f, 0x00, sizeof(f));
2470  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2471 
2472  const char *buf = "HTTP";
2473  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2474  buf = "220 ";
2475  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2476 
2478  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2479  * it sets internal structures which depends on the above function. */
2482 
2483  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2484  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2485  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2486  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2489 
2490  bool rdir = false;
2491  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2492  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2493  pm_results, &rdir);
2494  FAIL_IF(cnt != 1);
2495  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2496 
2500  PASS;
2501 }
2502 
2503 static int AppLayerProtoDetectTest07(void)
2504 {
2507 
2508  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2509  Flow f;
2510  memset(&f, 0x00, sizeof(f));
2511  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2512  AppProto pm_results[ALPROTO_MAX];
2513  memset(pm_results, 0, sizeof(pm_results));
2514 
2515  const char *buf = "HTTP";
2516  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2517 
2519  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2520  * it sets internal structures which depends on the above function. */
2522 
2523  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2524  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2525  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2526  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2528 
2529  bool rdir = false;
2530  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2531  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2532  pm_results, &rdir);
2533  FAIL_IF(cnt != 0);
2534 
2538  PASS;
2539 }
2540 
2541 static int AppLayerProtoDetectTest08(void)
2542 {
2545 
2546  uint8_t l7data[] = {
2547  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2548  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2549  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2550  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2551  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2552  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2553  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2554  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2555  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2556  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2557  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2558  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2559  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2560  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2561  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2562  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2563  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2564  0x00
2565  };
2566  AppProto pm_results[ALPROTO_MAX];
2567  memset(pm_results, 0, sizeof(pm_results));
2568  Flow f;
2569  memset(&f, 0x00, sizeof(f));
2570  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2571 
2572  const char *buf = "|ff|SMB";
2573  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2574 
2576  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2577  * it sets internal structures which depends on the above function. */
2580 
2581  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2582  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2583  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2584  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2586 
2587  bool rdir = false;
2588  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2589  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2590  pm_results, &rdir);
2591  FAIL_IF(cnt != 1);
2592  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2593 
2597  PASS;
2598 }
2599 
2600 static int AppLayerProtoDetectTest09(void)
2601 {
2604 
2605  uint8_t l7data[] = {
2606  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2607  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2608  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2609  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2610  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2611  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2612  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2613  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2614  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2615  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2616  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2617  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2618  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2619  0x00, 0x02, 0x02
2620  };
2621  AppProto pm_results[ALPROTO_MAX];
2622  memset(pm_results, 0, sizeof(pm_results));
2623  Flow f;
2624  memset(&f, 0x00, sizeof(f));
2625  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2626 
2627  const char *buf = "|fe|SMB";
2628  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2629 
2631  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2632  * it sets internal structures which depends on the above function. */
2635 
2636  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2637  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2638  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2639  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2641 
2642  bool rdir = false;
2643  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2644  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2645  pm_results, &rdir);
2646  FAIL_IF(cnt != 1);
2647  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2648 
2652  PASS;
2653 }
2654 
2655 static int AppLayerProtoDetectTest10(void)
2656 {
2659 
2660  uint8_t l7data[] = {
2661  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2662  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2663  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2664  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2665  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2666  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2667  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2668  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2669  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2670  };
2671  AppProto pm_results[ALPROTO_MAX];
2672  memset(pm_results, 0, sizeof(pm_results));
2673  Flow f;
2674  memset(&f, 0x00, sizeof(f));
2675  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2676 
2677  const char *buf = "|05 00|";
2678  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2679 
2681  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2682  * it sets internal structures which depends on the above function. */
2685 
2686  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2687  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2688  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2689  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2691 
2692  bool rdir = false;
2693  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2694  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2695  pm_results, &rdir);
2696  FAIL_IF(cnt != 1);
2697  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2698 
2702  PASS;
2703 }
2704 
2705 /**
2706  * \test Why we still get http for connect... obviously because
2707  * we also match on the reply, duh
2708  */
2709 static int AppLayerProtoDetectTest11(void)
2710 {
2713 
2714  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2715  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2716  AppProto pm_results[ALPROTO_MAX];
2717  memset(pm_results, 0, sizeof(pm_results));
2718  Flow f;
2719  memset(&f, 0x00, sizeof(f));
2720  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2721 
2723  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2725  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2727  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2729  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2731  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2733  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2735  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2737  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2738 
2740  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2741  * it sets internal structures which depends on the above function. */
2744 
2745  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2746  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2747  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2748  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2749 
2758 
2759  bool rdir = false;
2760  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2761  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2762  pm_results, &rdir);
2763  FAIL_IF(cnt != 1);
2764  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2765 
2766  memset(pm_results, 0, sizeof(pm_results));
2767  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2768  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2769  pm_results, &rdir);
2770  FAIL_IF(cnt != 1);
2771  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2772 
2776  PASS;
2777 }
2778 
2779 /**
2780  * \test AlpProtoSignature test
2781  */
2782 static int AppLayerProtoDetectTest12(void)
2783 {
2786 
2787  int r = 0;
2788 
2790  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2791  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2792  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2793  {
2794  printf("failure 1\n");
2795  goto end;
2796  }
2797 
2799  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2800  printf("failure 2\n");
2801  goto end;
2802  }
2803  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2804  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2805  {
2806  printf("failure 3\n");
2807  goto end;
2808  }
2809  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2810  printf("failure 4\n");
2811  goto end;
2812  }
2813  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2814  printf("failure 5\n");
2815  goto end;
2816  }
2817  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2818  printf("failure 6\n");
2819  goto end;
2820  }
2821 
2822  r = 1;
2823 
2824  end:
2827  return r;
2828 }
2829 
2830 /**
2831  * \test What about if we add some sigs only for udp but call for tcp?
2832  * It should not detect any proto
2833  */
2834 static int AppLayerProtoDetectTest13(void)
2835 {
2838 
2839  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2840  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2841  AppProto pm_results[ALPROTO_MAX];
2842 
2843  Flow f;
2844  memset(&f, 0x00, sizeof(f));
2845  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2846 
2848  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2850  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2852  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2854  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2856  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2858  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2860  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2862  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2863 
2865  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2866  * it sets internal structures which depends on the above function. */
2868 
2869  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2870  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2871 
2880 
2881  memset(pm_results, 0, sizeof(pm_results));
2882  bool rdir = false;
2883  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2884  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2885  pm_results, &rdir);
2886  FAIL_IF(cnt != 0);
2887 
2888  memset(pm_results, 0, sizeof(pm_results));
2889  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2890  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2891  pm_results, &rdir);
2892  FAIL_IF(cnt != 0);
2893 
2897  PASS;
2898 }
2899 
2900 /**
2901  * \test What about if we add some sigs only for udp calling it for UDP?
2902  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2903  * to ensure that TCP/UDP differences work correctly.
2904  */
2905 static int AppLayerProtoDetectTest14(void)
2906 {
2909 
2910  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2911  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2912  AppProto pm_results[ALPROTO_MAX];
2913  uint32_t cnt;
2914  Flow f;
2915  memset(&f, 0x00, sizeof(f));
2916  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2917 
2919  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2921  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2923  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2925  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2927  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2929  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2931  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2933  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2934 
2936  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2937  * it sets internal structures which depends on the above function. */
2940 
2941  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2942  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2943 
2952 
2953  memset(pm_results, 0, sizeof(pm_results));
2954  bool rdir = false;
2955  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2956  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2957  pm_results, &rdir);
2958  FAIL_IF(cnt != 1);
2959  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2960 
2961  memset(pm_results, 0, sizeof(pm_results));
2962  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2963  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2964  pm_results, &rdir);
2965  FAIL_IF(cnt != 1);
2966  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2967 
2971  PASS;
2972 }
2973 
2975  const char *alproto_name;
2977  uint16_t port;
2978  uint32_t alproto_mask;
2979  uint32_t min_depth;
2980  uint32_t max_depth;
2982 
2984  uint16_t port;
2985  uint32_t alproto_mask;
2986  uint16_t dp_max_depth;
2987  uint16_t sp_max_depth;
2988 
2994 
2995 
2997  uint8_t ipproto;
2998 
3002 
3003 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
3005  int no_of_ip_proto)
3006 {
3007  int result = 0;
3008  int i = -1, j = -1 , k = -1;
3009 #ifdef DEBUG
3010  int dir = 0;
3011 #endif
3012  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
3013  if (pp->ipproto != ip_proto[i].ipproto)
3014  goto end;
3015 
3017  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
3018  if (pp_port->port != ip_proto[i].port[k].port)
3019  goto end;
3020  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
3021  goto end;
3022  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
3023  goto end;
3024  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
3025  goto end;
3026  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
3027  goto end;
3028 
3029  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
3030 #ifdef DEBUG
3031  dir = 0;
3032 #endif
3033  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
3034  j++, pp_element = pp_element->next) {
3035 
3036  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
3037  goto end;
3038  }
3039  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
3040  goto end;
3041  }
3042  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
3043  goto end;
3044  }
3045  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
3046  goto end;
3047  }
3048  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
3049  goto end;
3050  }
3051  } /* for */
3052  if (pp_element != NULL)
3053  goto end;
3054 
3055  pp_element = pp_port->sp;
3056 #ifdef DEBUG
3057  dir = 1;
3058 #endif
3059  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
3060  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
3061  goto end;
3062  }
3063  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
3064  goto end;
3065  }
3066  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
3067  goto end;
3068  }
3069  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
3070  goto end;
3071  }
3072  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
3073  goto end;
3074  }
3075  } /* for */
3076  if (pp_element != NULL)
3077  goto end;
3078  }
3079  if (pp_port != NULL)
3080  goto end;
3081  }
3082  if (pp != NULL)
3083  goto end;
3084 
3085  result = 1;
3086  end:
3087 #ifdef DEBUG
3088  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
3089 #endif
3090  return result;
3091 }
3092 
3093 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
3094  const uint8_t *input,
3095  uint32_t input_len, uint8_t *rdir)
3096 {
3097  return 0;
3098 }
3099 
3100 static int AppLayerProtoDetectTest15(void)
3101 {
3104 
3105  int result = 0;
3106 
3107  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
3108  ProbingParserDummyForTesting, NULL);
3109  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3110  "80",
3111  ALPROTO_SMB,
3112  5, 6,
3113  STREAM_TOSERVER,
3114  ProbingParserDummyForTesting, NULL);
3115  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3116  "80",
3117  ALPROTO_FTP,
3118  7, 10,
3119  STREAM_TOSERVER,
3120  ProbingParserDummyForTesting, NULL);
3121 
3122  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3123  "81",
3125  9, 10,
3126  STREAM_TOSERVER,
3127  ProbingParserDummyForTesting, NULL);
3128  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3129  "81",
3130  ALPROTO_FTP,
3131  7, 15,
3132  STREAM_TOSERVER,
3133  ProbingParserDummyForTesting, NULL);
3134  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3135  "0",
3136  ALPROTO_SMTP,
3137  12, 0,
3138  STREAM_TOSERVER,
3139  ProbingParserDummyForTesting, NULL);
3140  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3141  "0",
3142  ALPROTO_TLS,
3143  12, 18,
3144  STREAM_TOSERVER,
3145  ProbingParserDummyForTesting, NULL);
3146 
3147  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3148  "85",
3150  9, 10,
3151  STREAM_TOSERVER,
3152  ProbingParserDummyForTesting, NULL);
3153  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3154  "85",
3155  ALPROTO_FTP,
3156  7, 15,
3157  STREAM_TOSERVER,
3158  ProbingParserDummyForTesting, NULL);
3159  result = 1;
3160 
3161  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3162  "85",
3163  ALPROTO_IMAP,
3164  12, 23,
3165  STREAM_TOSERVER,
3166  ProbingParserDummyForTesting, NULL);
3167 
3168  /* toclient */
3169  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3170  "0",
3172  12, 23,
3173  STREAM_TOCLIENT,
3174  ProbingParserDummyForTesting, NULL);
3175  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3176  "0",
3177  ALPROTO_IRC,
3178  12, 14,
3179  STREAM_TOCLIENT,
3180  ProbingParserDummyForTesting, NULL);
3181 
3182  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3183  "85",
3185  9, 10,
3186  STREAM_TOCLIENT,
3187  ProbingParserDummyForTesting, NULL);
3188  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3189  "81",
3190  ALPROTO_FTP,
3191  7, 15,
3192  STREAM_TOCLIENT,
3193  ProbingParserDummyForTesting, NULL);
3194  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3195  "0",
3196  ALPROTO_TLS,
3197  12, 18,
3198  STREAM_TOCLIENT,
3199  ProbingParserDummyForTesting, NULL);
3200  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3201  ProbingParserDummyForTesting, NULL);
3202  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3203  "81",
3205  9, 10,
3206  STREAM_TOCLIENT,
3207  ProbingParserDummyForTesting, NULL);
3208  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3209  "90",
3210  ALPROTO_FTP,
3211  7, 15,
3212  STREAM_TOCLIENT,
3213  ProbingParserDummyForTesting, NULL);
3214  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3215  "80",
3216  ALPROTO_SMB,
3217  5, 6,
3218  STREAM_TOCLIENT,
3219  ProbingParserDummyForTesting, NULL);
3220  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3221  "85",
3222  ALPROTO_IMAP,
3223  12, 23,
3224  STREAM_TOCLIENT,
3225  ProbingParserDummyForTesting, NULL);
3226  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3227  "0",
3228  ALPROTO_SMTP,
3229  12, 17,
3230  STREAM_TOCLIENT,
3231  ProbingParserDummyForTesting, NULL);
3232  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3233  "80",
3234  ALPROTO_FTP,
3235  7, 10,
3236  STREAM_TOCLIENT,
3237  ProbingParserDummyForTesting, NULL);
3238 
3239  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3240  { "http", ALPROTO_HTTP1, 80, 1 << ALPROTO_HTTP1, 5, 8 },
3241  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3242  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3243  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3244  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3245  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3246  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3247  };
3248  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80,
3249  1 << ALPROTO_HTTP1, 5, 8 },
3250  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3251  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3252  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3253  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3254  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3255  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 } };
3256 
3257  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3258  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3259  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3260  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3261  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3262  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3263  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3264  };
3265  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3266  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3267  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3268  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3269  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3270  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3271  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3272  };
3273 
3274  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3275  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3276  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3277  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3278  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3279  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3280  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3281  };
3282  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3283  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3284  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3285  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3286  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3287  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3288  };
3289 
3290  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3291  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3292  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3293  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3294  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3295  };
3296  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3297  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3298  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3299  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3300  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3301  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3302  };
3303 
3304  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3305  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3306  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3307  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3308  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3309  };
3310  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3311  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3312  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3313  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3314  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3315  };
3316 
3317 
3318  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3319  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3320  };
3321  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3322  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3323  };
3324 
3325  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3326  {
3327  80,
3328  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3329  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3330  (1 << ALPROTO_JABBER)),
3331  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3332  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3333  (1 << ALPROTO_SMTP)),
3334  23,
3335  element_ts_80,
3336  element_tc_80,
3337  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3338  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3339  },
3340  {
3341  81,
3342  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3343  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3344  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) |
3345  (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3346  23,
3347  element_ts_81,
3348  element_tc_81,
3349  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3350  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3351  },
3352  { 85,
3353  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3354  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3355  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3356  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3357  23, element_ts_85, element_tc_85,
3358  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3359  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3360  { 90,
3361  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3362  (1 << ALPROTO_JABBER)),
3363  ((1 << ALPROTO_FTP) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3364  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3365  23, element_ts_90, element_tc_90,
3366  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3367  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3368  { 0,
3369  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3370  (1 << ALPROTO_JABBER)),
3371  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3372  (1 << ALPROTO_SMTP)),
3373  23, element_ts_0, element_tc_0,
3374  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3375  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3376  };
3377 
3378  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3379  { 85,
3380  (1 << ALPROTO_IMAP),
3381  (1 << ALPROTO_IMAP),
3382  23,
3383  element_ts_85_udp, element_tc_85_udp,
3384  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3385  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3386  },
3387  };
3388 
3390  { IPPROTO_TCP,
3391  ports_tcp,
3392  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3393  },
3394  { IPPROTO_UDP,
3395  ports_udp,
3396  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3397  },
3398  };
3399 
3400 
3401  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3402  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3403  goto end;
3404  }
3405  result = 1;
3406 
3407  end:
3410  return result;
3411 }
3412 
3413 
3414 /** \test test if the engine detect the proto and match with it */
3415 static int AppLayerProtoDetectTest16(void)
3416 {
3417  int result = 0;
3418  Flow *f = NULL;
3419  HtpState *http_state = NULL;
3420  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3421  "User-Agent: Mozilla/1.0\r\n"
3422  "Cookie: hellocatch\r\n\r\n";
3423  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3424  TcpSession ssn;
3425  Packet *p = NULL;
3426  Signature *s = NULL;
3427  ThreadVars tv;
3428  DetectEngineThreadCtx *det_ctx = NULL;
3429  DetectEngineCtx *de_ctx = NULL;
3431 
3432  memset(&tv, 0, sizeof(ThreadVars));
3433  memset(&ssn, 0, sizeof(TcpSession));
3434 
3435  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3436  if (p == NULL) {
3437  printf("packet setup failed: ");
3438  goto end;
3439  }
3440 
3441  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3442  if (f == NULL) {
3443  printf("flow setup failed: ");
3444  goto end;
3445  }
3446  f->protoctx = &ssn;
3447  f->proto = IPPROTO_TCP;
3448  p->flow = f;
3449 
3453 
3454  f->alproto = ALPROTO_HTTP1;
3455 
3456  StreamTcpInitConfig(true);
3457 
3459  if (de_ctx == NULL) {
3460  goto end;
3461  }
3462  de_ctx->flags |= DE_QUIET;
3463 
3464  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3465  "(msg:\"Test content option\"; "
3466  "sid:1;)");
3467  if (s == NULL) {
3468  goto end;
3469  }
3470 
3472  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3473 
3474  int r = AppLayerParserParse(
3475  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3476  if (r != 0) {
3477  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3478  goto end;
3479  }
3480 
3481  http_state = f->alstate;
3482  if (http_state == NULL) {
3483  printf("no http state: ");
3484  goto end;
3485  }
3486 
3487  /* do detect */
3488  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3489 
3490  if (!PacketAlertCheck(p, 1)) {
3491  printf("sig 1 didn't alert, but it should: ");
3492  goto end;
3493  }
3494  result = 1;
3495  end:
3496  if (alp_tctx != NULL)
3498  if (det_ctx != NULL)
3499  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3500  if (de_ctx != NULL)
3502  if (de_ctx != NULL)
3504 
3505  StreamTcpFreeConfig(true);
3506 
3507  UTHFreePackets(&p, 1);
3508  UTHFreeFlow(f);
3509  return result;
3510 }
3511 
3512 /** \test test if the engine detect the proto on a non standar port
3513  * and match with it */
3514 static int AppLayerProtoDetectTest17(void)
3515 {
3516  int result = 0;
3517  Flow *f = NULL;
3518  HtpState *http_state = NULL;
3519  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3520  "User-Agent: Mozilla/1.0\r\n"
3521  "Cookie: hellocatch\r\n\r\n";
3522  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3523  TcpSession ssn;
3524  Packet *p = NULL;
3525  Signature *s = NULL;
3526  ThreadVars tv;
3527  DetectEngineThreadCtx *det_ctx = NULL;
3528  DetectEngineCtx *de_ctx = NULL;
3530 
3531  memset(&tv, 0, sizeof(ThreadVars));
3532  memset(&ssn, 0, sizeof(TcpSession));
3533 
3534  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3535 
3536  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3537  if (f == NULL)
3538  goto end;
3539  f->protoctx = &ssn;
3540  f->proto = IPPROTO_TCP;
3541  p->flow = f;
3545  f->alproto = ALPROTO_HTTP1;
3546 
3547  StreamTcpInitConfig(true);
3548 
3550  if (de_ctx == NULL) {
3551  goto end;
3552  }
3553  de_ctx->flags |= DE_QUIET;
3554 
3555  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3556  "(msg:\"http over non standar port\"; "
3557  "sid:1;)");
3558  if (s == NULL) {
3559  goto end;
3560  }
3561 
3563  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3564 
3565  int r = AppLayerParserParse(
3566  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3567  if (r != 0) {
3568  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3569  goto end;
3570  }
3571 
3572  http_state = f->alstate;
3573  if (http_state == NULL) {
3574  printf("no http state: ");
3575  goto end;
3576  }
3577 
3578  /* do detect */
3579  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3580 
3581  if (!PacketAlertCheck(p, 1)) {
3582  printf("sig 1 didn't alert, but it should: ");
3583  goto end;
3584  }
3585 
3586  result = 1;
3587 
3588  end:
3589  if (alp_tctx != NULL)
3591  if (det_ctx != NULL)
3592  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3593  if (de_ctx != NULL)
3595  if (de_ctx != NULL)
3597 
3598  StreamTcpFreeConfig(true);
3599 
3600  UTHFreePackets(&p, 1);
3601  UTHFreeFlow(f);
3602  return result;
3603 }
3604 
3605 /** \test test if the engine detect the proto and doesn't match
3606  * because the sig expects another proto (ex ftp)*/
3607 static int AppLayerProtoDetectTest18(void)
3608 {
3609  int result = 0;
3610  Flow *f = NULL;
3611  HtpState *http_state = NULL;
3612  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3613  "User-Agent: Mozilla/1.0\r\n"
3614  "Cookie: hellocatch\r\n\r\n";
3615  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3616  TcpSession ssn;
3617  Packet *p = NULL;
3618  Signature *s = NULL;
3619  ThreadVars tv;
3620  DetectEngineThreadCtx *det_ctx = NULL;
3621  DetectEngineCtx *de_ctx = NULL;
3623 
3624  memset(&tv, 0, sizeof(ThreadVars));
3625  memset(&ssn, 0, sizeof(TcpSession));
3626 
3627  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3628 
3629  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3630  if (f == NULL)
3631  goto end;
3632  f->protoctx = &ssn;
3633  f->proto = IPPROTO_TCP;
3634  p->flow = f;
3638  f->alproto = ALPROTO_HTTP1;
3639 
3640  StreamTcpInitConfig(true);
3641 
3643  if (de_ctx == NULL) {
3644  goto end;
3645  }
3646  de_ctx->flags |= DE_QUIET;
3647 
3648  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3649  "(msg:\"Test content option\"; "
3650  "sid:1;)");
3651  if (s == NULL) {
3652  goto end;
3653  }
3654 
3656  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3657 
3658  int r = AppLayerParserParse(
3659  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3660  if (r != 0) {
3661  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3662  goto end;
3663  }
3664 
3665  http_state = f->alstate;
3666  if (http_state == NULL) {
3667  printf("no http state: ");
3668  goto end;
3669  }
3670 
3671  /* do detect */
3672  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3673 
3674  if (PacketAlertCheck(p, 1)) {
3675  printf("sig 1 alerted, but it should not (it's not ftp): ");
3676  goto end;
3677  }
3678 
3679  result = 1;
3680  end:
3681  if (alp_tctx != NULL)
3683  if (det_ctx != NULL)
3684  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3685  if (de_ctx != NULL)
3687  if (de_ctx != NULL)
3689 
3690  StreamTcpFreeConfig(true);
3691 
3692  UTHFreePackets(&p, 1);
3693  UTHFreeFlow(f);
3694  return result;
3695 }
3696 
3697 /** \test test if the engine detect the proto and doesn't match
3698  * because the packet has another proto (ex ftp) */
3699 static int AppLayerProtoDetectTest19(void)
3700 {
3701  int result = 0;
3702  Flow *f = NULL;
3703  uint8_t http_buf1[] = "MPUT one\r\n";
3704  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3705  TcpSession ssn;
3706  Packet *p = NULL;
3707  Signature *s = NULL;
3708  ThreadVars tv;
3709  DetectEngineThreadCtx *det_ctx = NULL;
3710  DetectEngineCtx *de_ctx = NULL;
3712 
3713  memset(&tv, 0, sizeof(ThreadVars));
3714  memset(&ssn, 0, sizeof(TcpSession));
3715 
3716  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3717 
3718  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3719  if (f == NULL)
3720  goto end;
3721  f->protoctx = &ssn;
3722  f->proto = IPPROTO_TCP;
3723  p->flow = f;
3727  f->alproto = ALPROTO_FTP;
3728 
3729  StreamTcpInitConfig(true);
3730 
3732  if (de_ctx == NULL) {
3733  goto end;
3734  }
3735  de_ctx->flags |= DE_QUIET;
3736 
3737  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3738  "(msg:\"http over non standar port\"; "
3739  "sid:1;)");
3740  if (s == NULL) {
3741  goto end;
3742  }
3743 
3745  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3746 
3747  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3748  STREAM_TOSERVER, http_buf1, http_buf1_len);
3749  if (r != 0) {
3750  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3751  goto end;
3752  }
3753 
3754  /* do detect */
3755  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3756 
3757  if (PacketAlertCheck(p, 1)) {
3758  printf("sig 1 alerted, but it should not (it's ftp): ");
3759  goto end;
3760  }
3761 
3762  result = 1;
3763 
3764  end:
3765  if (alp_tctx != NULL)
3767  if (det_ctx != NULL)
3768  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3769  if (de_ctx != NULL)
3771  if (de_ctx != NULL)
3773 
3774  StreamTcpFreeConfig(true);
3775  UTHFreePackets(&p, 1);
3776  UTHFreeFlow(f);
3777  return result;
3778 }
3779 
3781 {
3782  SCEnter();
3783 
3784  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3785  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3786  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3787  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3788  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3789  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3790  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3791  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3792  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3793  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3794  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3795  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3796  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3797  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3798  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3799  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3800  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3801  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3802  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3803 
3804  SCReturn;
3805 }
3806 
3807 #endif /* UNITTESTS */
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2983
DETECT_CONTENT_NOCASE
#define DETECT_CONTENT_NOCASE
Definition: detect-content.h:29
AppLayerProtoDetectPMCtx_
Definition: app-layer-detect-proto.c:123
AppLayerProtoDetectProbingParserElement_
Definition: app-layer-detect-proto.c:68
AppLayerProtoDetectThreadCtx_::mpm_tctx
MpmThreadCtx mpm_tctx[FLOW_PROTO_DEFAULT][2]
Definition: app-layer-detect-proto.c:176
PmqReset
void PmqReset(PrefilterRuleStore *pmq)
Reset a Pmq for reusage. Meant to be called after a single search.
Definition: util-prefilter.c:102
FLOW_RESET_PP_DONE
#define FLOW_RESET_PP_DONE(f, dir)
Definition: flow.h:286
AppLayerProtoDetectUnittestCtxRestore
void AppLayerProtoDetectUnittestCtxRestore(void)
Restores back the internal context used by the app layer proto detection module, that was previously ...
Definition: app-layer-detect-proto.c:2279
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:102
AppLayerProtoDetectPMSignature_::cd
DetectContentData * cd
Definition: app-layer-detect-proto.c:116
AppLayerProtoDetectPMCtx_::max_pat_id
PatIntId max_pat_id
Definition: app-layer-detect-proto.c:135
tm-threads.h
AppLayerProtoDetectPMSignature_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:112
AppLayerProtoDetectPPParseConfPorts
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
Definition: app-layer-detect-proto.c:1731
detect-content.h
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:91
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
AppLayerProtoDetectSetup
int AppLayerProtoDetectSetup(void)
The first function to be called. This initializes a global protocol detection context.
Definition: app-layer-detect-proto.c:1847
AppLayerProtoDetectProbingParser_::next
struct AppLayerProtoDetectProbingParser_ * next
Definition: app-layer-detect-proto.c:108
ALPROTO_IKE
@ ALPROTO_IKE
Definition: app-layer-protos.h:49
FlowSetChangeProtoFlag
void FlowSetChangeProtoFlag(Flow *f)
Set flag to indicate to change proto for the flow.
Definition: flow.c:211
AppLayerProtoDetectPMRegisterPatternCI
int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-insensitive pattern for protocol detection.
Definition: app-layer-detect-proto.c:1832
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1003
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ALPROTO_DCERPC
@ ALPROTO_DCERPC
Definition: app-layer-protos.h:38
MpmTableElmt_::InitThreadCtx
void(* InitThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:149
FLOW_IS_PE_DONE
#define FLOW_IS_PE_DONE(f, dir)
Definition: flow.h:279
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
AppLayerExpectationSetup
void AppLayerExpectationSetup(void)
Definition: app-layer-expectation.c:146
FLOW_SET_PM_DONE
#define FLOW_SET_PM_DONE(f, dir)
Definition: flow.h:281
AppLayerProtoDetectProbingParserElement_::min_depth
uint16_t min_depth
Definition: app-layer-detect-proto.c:75
MpmThreadCtx_
Definition: util-mpm.h:47
ConfNode_::val
char * val
Definition: conf.h:34
stream-tcp.h
PrefilterRuleStore_::rule_id_array_cnt
uint32_t rule_id_array_cnt
Definition: util-prefilter.h:40
ALPROTO_ENIP
@ ALPROTO_ENIP
Definition: app-layer-protos.h:43
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
AppLayerRequestProtocolTLSUpgrade
bool AppLayerRequestProtocolTLSUpgrade(Flow *f)
request applayer to wrap up this protocol and rerun protocol detection with expectation of TLS....
Definition: app-layer-detect-proto.c:1990
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ALPROTO_TLS
@ ALPROTO_TLS
Definition: app-layer-protos.h:33
PrefilterRuleStore_
structure for storing potential rule matches
Definition: util-prefilter.h:34
AppLayerProtoDetectPMCtx_::map
AppLayerProtoDetectPMSignature ** map
Definition: app-layer-detect-proto.c:131
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
DetectPort_::port
uint16_t port
Definition: detect.h:183
AppLayerProtoDetectProbingParserPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:90
ALPROTO_MODBUS
@ ALPROTO_MODBUS
Definition: app-layer-protos.h:42
Flow_::proto
uint8_t proto
Definition: flow.h:379
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
ALPROTO_QUIC
@ ALPROTO_QUIC
Definition: app-layer-protos.h:51
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:141
AppLayerProtoDetectProbingParserElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:69
Packet_::flags
uint32_t flags
Definition: decode.h:463
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
threads.h
AppLayerProtoDetectAliases
struct AppLayerProtoDetectAliases_ AppLayerProtoDetectAliases
ALPROTO_JABBER
@ ALPROTO_JABBER
Definition: app-layer-protos.h:36
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:357
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2271
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2975
Flow_::protomap
uint8_t protomap
Definition: flow.h:451
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
ALPROTO_IRC
@ ALPROTO_IRC
Definition: app-layer-protos.h:39
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:787
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:462
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2455
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2164
ALPROTO_SIP
@ ALPROTO_SIP
Definition: app-layer-protos.h:54
AppLayerProtoDetectProbingParserPort_::sp
AppLayerProtoDetectProbingParserElement * sp
Definition: app-layer-detect-proto.c:99
AppLayerRequestProtocolChange
bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
request applayer to wrap up this protocol and rerun protocol detection.
Definition: app-layer-detect-proto.c:1959
AppLayerProtoDetectCtx_::ctx_ipp
AppLayerProtoDetectCtxIpproto ctx_ipp[FLOW_PROTO_DEFAULT]
Definition: app-layer-detect-proto.c:151
AppLayerProtoDetectAliases_::proto_alias
const char * proto_alias
Definition: app-layer-detect-proto.c:166
AppLayerProtoDetectPMSignature_::PPFunc
ProbingParserFPtr PPFunc
Definition: app-layer-detect-proto.c:119
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:314
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:227
MIN
#define MIN(x, y)
Definition: suricata-common.h:380
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:289
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:196
ALPROTO_FTP
@ ALPROTO_FTP
Definition: app-layer-protos.h:31
AppLayerProtoDetectPPTestDataElement_::min_depth
uint32_t min_depth
Definition: app-layer-detect-proto.c:2979
PatIntId
#define PatIntId
Definition: suricata-common.h:307
stream-tcp-reassemble.h
ProbingParserFPtr
AppProto(* ProbingParserFPtr)(Flow *f, uint8_t flags, const uint8_t *input, uint32_t input_len, uint8_t *rdir)
Definition: app-layer-detect-proto.h:33
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:337
AppLayerProtoDetectPPTestDataElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:2976
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1809
AppLayerProtoDetectProbingParserElement
struct AppLayerProtoDetectProbingParserElement_ AppLayerProtoDetectProbingParserElement
proto
uint8_t proto
Definition: decode-template.h:0
m
SCMutex m
Definition: flow-hash.h:6
DetectContentData_
Definition: detect-content.h:88
UTHBuildPacketSrcDstPorts
Packet * UTHBuildPacketSrcDstPorts(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, uint16_t sport, uint16_t dport)
UTHBuildPacketSrcDstPorts is a wrapper that build packets specifying src and dst ports and defaulting...
Definition: util-unittest-helper.c:454
AppLayerProtoDetectPMSignature_
Definition: app-layer-detect-proto.c:111
MpmCtx_::maxdepth
uint16_t maxdepth
Definition: util-mpm.h:95
ALPROTO_SSH
@ ALPROTO_SSH
Definition: app-layer-protos.h:34
ALPROTO_DHCP
@ ALPROTO_DHCP
Definition: app-layer-protos.h:52
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:459
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:115
ALPROTO_MAX
@ ALPROTO_MAX
Definition: app-layer-protos.h:75
Flow_::protoctx
void * protoctx
Definition: flow.h:447
AppLayerProtoDetectProbingParser_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:105
AppLayerProtoDetectProbingParserPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:96
DetectPort_::port2
uint16_t port2
Definition: detect.h:184
DetectContentFree
void DetectContentFree(DetectEngineCtx *de_ctx, void *ptr)
this function will SCFree memory associated with DetectContentData
Definition: detect-content.c:378
AppLayerProtoDetectPPTestDataElement_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2978
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:112
HtpState_
Definition: app-layer-htp.h:244
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:536
FLOW_SET_PP_DONE
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:282
util-unittest-helper.h
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2996
ALPROTO_KRB5
@ ALPROTO_KRB5
Definition: app-layer-protos.h:50
ALPROTO_SNMP
@ ALPROTO_SNMP
Definition: app-layer-protos.h:53
util-memcmp.h
FLOW_IS_PM_DONE
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:277
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
Definition: util-mpm.c:203
AppLayerProtoDetectPPRegister
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
Definition: app-layer-detect-proto.c:1692
AppLayerProtoDetectCtx_::spm_global_thread_ctx
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition: app-layer-detect-proto.c:154
AppLayerProtoDetectProbingParserPort_::dp
AppLayerProtoDetectProbingParserElement * dp
Definition: app-layer-detect-proto.c:98
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:481
app-layer-expectation.h
app-layer-detect-proto.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:359
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:521
AppLayerExpectationHandle
AppProto AppLayerExpectationHandle(Flow *f, uint8_t flags)
Definition: app-layer-expectation.c:303
expectation_proto
uint8_t expectation_proto[ALPROTO_MAX]
Definition: app-layer-detect-proto.c:2239
app-layer-htp.h
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1252
AppLayerProtoDetectThreadCtx_
The app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:173
Flow_::protodetect_dp
uint16_t protodetect_dp
Definition: flow.h:433
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
AppLayerProtoDetectProbingParserElement_::ProbingParserTs
ProbingParserFPtr ProbingParserTs
Definition: app-layer-detect-proto.c:80
FLOW_IS_PP_DONE
#define FLOW_IS_PP_DONE(f, dir)
Definition: flow.h:278
DetectEngineThreadCtx_
Definition: detect.h:1027
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:73
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:44
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:32
AppLayerProtoDetectProbingParserPort
struct AppLayerProtoDetectProbingParserPort_ AppLayerProtoDetectProbingParserPort
AppLayerProtoDetectProbingParserPort_::dp_max_depth
uint16_t dp_max_depth
Definition: app-layer-detect-proto.c:95
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:22
StringToAppProto
AppProto StringToAppProto(const char *proto_name)
Maps a string to its ALPROTO_* equivalent.
Definition: app-layer-protos.c:149
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
AppLayerProtoDetectProbingParserPort_::next
struct AppLayerProtoDetectProbingParserPort_ * next
Definition: app-layer-detect-proto.c:101
AppLayerProtoDetectReset
void AppLayerProtoDetectReset(Flow *f)
Reset proto detect for flow.
Definition: app-layer-detect-proto.c:1995
AppLayerProtoDetectPMRegisterPatternCSwPP
int AppLayerProtoDetectPMRegisterPatternCSwPP(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction, ProbingParserFPtr PPFunc, uint16_t pp_min_depth, uint16_t pp_max_depth)
Definition: app-layer-detect-proto.c:1818
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2989
alpd_tctx
AppLayerProtoDetectThreadCtx * alpd_tctx
Definition: fuzz_applayerprotodetectgetproto.c:25
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2118
DetectPort_
Port structure for detection engine.
Definition: detect.h:182
AppLayerProtoDetectProbingParserPort_
Definition: app-layer-detect-proto.c:88
DetectContentData_::id
PatIntId id
Definition: detect-content.h:100
app-layer-parser.h
AppLayerProtoDetectPPTestDataIPProto_::no_of_port
int no_of_port
Definition: app-layer-detect-proto.c:3000
AppLayerProtoDetectCtx_
The app layer protocol detection context.
Definition: app-layer-detect-proto.c:147
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
AppLayerProtoDetectProbingParserElement_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:73
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2019
SCReturn
#define SCReturn
Definition: util-debug.h:273
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:285
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:101
stream.h
SpmScan
uint8_t * SpmScan(const SpmCtx *ctx, SpmThreadCtx *thread_ctx, const uint8_t *haystack, uint32_t haystack_len)
Definition: util-spm.c:193
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:98
AppLayerProtoDetectPPTestDataPort_::toclient_element
AppLayerProtoDetectPPTestDataElement * toclient_element
Definition: app-layer-detect-proto.c:2990
Packet_
Definition: decode.h:428
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:167
detect-engine-build.h
ALPROTO_IMAP
@ ALPROTO_IMAP
Definition: app-layer-protos.h:35
FLOW_GET_SP
#define FLOW_GET_SP(f)
Definition: flow.h:165
stream-tcp-private.h
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h:277
detect-engine-alert.h
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:99
AppLayerProtoDetectPMCtx_::head
AppLayerProtoDetectPMSignature * head
Definition: app-layer-detect-proto.c:132
SinglePatternMatchDefaultMatcher
uint16_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition: util-spm.c:68
AppLayerRegisterExpectationProto
void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
Definition: app-layer-detect-proto.c:2252
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2992
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:166
ALPROTO_TELNET
@ ALPROTO_TELNET
Definition: app-layer-protos.h:58
SpmMakeThreadCtx
SpmThreadCtx * SpmMakeThreadCtx(const SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:153
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1909
AppLayerProtoDetectPMSignature_::pp_min_depth
uint16_t pp_min_depth
Definition: app-layer-detect-proto.c:117
AppLayerProtoDetectPMCtx_::max_sig_id
SigIntId max_sig_id
Definition: app-layer-detect-proto.c:136
ALPROTO_TFTP
@ ALPROTO_TFTP
Definition: app-layer-protos.h:48
ALPROTO_HTTP2
@ ALPROTO_HTTP2
Definition: app-layer-protos.h:61
AppLayerProtoDetectPPTestDataPort_::dp_max_depth
uint16_t dp_max_depth
Definition: app-layer-detect-proto.c:2986
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:425
AppLayerProtoDetectPMSignature_::pp_max_depth
uint16_t pp_max_depth
Definition: app-layer-detect-proto.c:118
AppLayerProtoDetectPPTestDataPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:2984
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:167
AppLayerProtoDetectPMCtx_::mpm_ctx
MpmCtx mpm_ctx
Definition: app-layer-detect-proto.c:126
MpmAddPatternCS
int MpmAddPatternCS(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:244
Flow_::alproto_expect
AppProto alproto_expect
Definition: flow.h:465
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:232
AppLayerProtoDetectThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: app-layer-detect-proto.c:177
AppLayerProtoDetectProbingParserElement_::max_depth
uint16_t max_depth
Definition: app-layer-detect-proto.c:77
AppLayerProtoDetectCtx
struct AppLayerProtoDetectCtx_ AppLayerProtoDetectCtx
The app layer protocol detection context.
SpmDestroyGlobalThreadCtx
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:144
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1951
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:424
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:526
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:293
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:785
AppLayerProtoDetectAliases_
Definition: app-layer-detect-proto.c:164
Packet_::flow
struct Flow_ * flow
Definition: decode.h:465
SpmDestroyThreadCtx
void SpmDestroyThreadCtx(SpmThreadCtx *thread_ctx)
Definition: util-spm.c:163
AppLayerProtoDetectPMSignature_::direction
uint8_t direction
Definition: app-layer-detect-proto.c:113
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3166
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:695
AppLayerProtoDetectPPTestDataPort_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2985
AppLayerProtoDetectPMSignature_::next
struct AppLayerProtoDetectPMSignature_ * next
Definition: app-layer-detect-proto.c:120
flags
uint8_t flags
Definition: decode-gre.h:0
AppLayerProtoDetectPPTestDataIPProto
struct AppLayerProtoDetectPPTestDataIPProto_ AppLayerProtoDetectPPTestDataIPProto
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1323
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:71
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3380
AppLayerProtoDetectAliases_::next
struct AppLayerProtoDetectAliases_ * next
Definition: app-layer-detect-proto.c:167
AppLayerProtoDetectPPTestDataIPProto_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:2997
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:98
AppLayerProtoDetectPMSignature
struct AppLayerProtoDetectPMSignature_ AppLayerProtoDetectPMSignature
FLOW_RESET_PE_DONE
#define FLOW_RESET_PE_DONE(f, dir)
Definition: flow.h:287
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:70
AppLayerProtoDetectDeSetup
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
Definition: app-layer-detect-proto.c:1877
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
ALPROTO_PGSQL
@ ALPROTO_PGSQL
Definition: app-layer-protos.h:57
SWAP_VARS
#define SWAP_VARS(type, a, b)
Definition: suricata-common.h:417
AppLayerProtoDetectPMSignature_::id
SigIntId id
Definition: app-layer-detect-proto.c:114
util-spm.h
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:89
ALPROTO_FTPDATA
@ ALPROTO_FTPDATA
Definition: app-layer-protos.h:47
PatternMatchDefaultMatcher
uint8_t PatternMatchDefaultMatcher(void)
Function to return the multi pattern matcher algorithm to be used by the engine, based on the mpm-alg...
Definition: detect-engine-mpm.c:847
AppLayerProtoDetectCtx_::alproto_names
const char * alproto_names[ALPROTO_MAX]
Definition: app-layer-detect-proto.c:161
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:793
AppLayerProtoDetectAliases_::proto_name
const char * proto_name
Definition: app-layer-detect-proto.c:165
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
AppLayerProtoDetectProbingParserElement_::next
struct AppLayerProtoDetectProbingParserElement_ * next
Definition: app-layer-detect-proto.c:85
TcpStreamCnf_::midstream
bool midstream
Definition: stream-tcp.h:59
threadvars.h
util-validate.h
SpmGlobalThreadCtx_
Definition: util-spm.h:47
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:106
AppLayerProtoDetectSupportedAppProtocols
void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
Definition: app-layer-detect-proto.c:2223
AppLayerProtoDetectGetProto
AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f, const uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t flags, bool *reverse_flow)
Returns the app layer protocol given a buffer.
Definition: app-layer-detect-proto.c:1545
AppLayerProtoDetectUnittestsRegister
void AppLayerProtoDetectUnittestsRegister(void)
Register unittests for app layer proto detection module.
Definition: app-layer-detect-proto.c:3780
AppLayerProtoDetectCtxIpproto_::ctx_pm
AppLayerProtoDetectPMCtx ctx_pm[2]
Definition: app-layer-detect-proto.c:141
AppLayerProtoDetectPPTestDataElement_::max_depth
uint32_t max_depth
Definition: app-layer-detect-proto.c:2980
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:2084
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2181
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:150
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alproto_ts
AppProto alproto_ts
Definition: flow.h:457
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:482
AppLayerProtoDetectCtxIpproto_
Definition: app-layer-detect-proto.c:139
AppLayerProtoDetectPMCtx_::pp_max_len
uint16_t pp_max_len
Definition: app-layer-detect-proto.c:124
detect-parse.h
Signature_
Signature container.
Definition: detect.h:542
ALPROTO_MQTT
@ ALPROTO_MQTT
Definition: app-layer-protos.h:56
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:561
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:66
AppLayerProtoDetectProbingParserElement_::ProbingParserTc
ProbingParserFPtr ProbingParserTc
Definition: app-layer-detect-proto.c:83
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:70
ALPROTO_TEMPLATE
@ ALPROTO_TEMPLATE
Definition: app-layer-protos.h:59
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:229
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2416
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
SCReturnCT
#define SCReturnCT(x, type)
Definition: util-debug.h:285
AppLayerProtoDetectRegisterAlias
void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
Definition: app-layer-detect-proto.c:1919
AppLayerProtoDetectThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: app-layer-detect-proto.c:174
app-layer-protos.h
AppLayerProtoDetectProbingParser_
Definition: app-layer-detect-proto.c:104
ALPROTO_RFB
@ ALPROTO_RFB
Definition: app-layer-protos.h:55
AppLayerProtoDetectPPTestDataPort_::ts_no_of_element
int ts_no_of_element
Definition: app-layer-detect-proto.c:2991
PmqFree
void PmqFree(PrefilterRuleStore *pmq)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:90
AppLayerProtoDetectPPTestDataPort
struct AppLayerProtoDetectPPTestDataPort_ AppLayerProtoDetectPPTestDataPort
AppLayerProtoDetectDestroyCtxThread
void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
Destroys the app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:2138
ALPROTO_BITTORRENT_DHT
@ ALPROTO_BITTORRENT_DHT
Definition: app-layer-protos.h:62
AppLayerProtoDetectProbingParserElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:71
ALPROTO_NTP
@ ALPROTO_NTP
Definition: app-layer-protos.h:46
ALPROTO_SMB
@ ALPROTO_SMB
Definition: app-layer-protos.h:37
likely
#define likely(expr)
Definition: util-optimize.h:32
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:788
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:151
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:66
DetectContentParseEncloseQuotes
DetectContentData * DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
Definition: detect-content.c:253
AppLayerProtoDetectPMRegisterPatternCS
int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-sensitive pattern for protocol detection.
Definition: app-layer-detect-proto.c:1805
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint16_t matcher)
Definition: util-spm.c:138
FlowChangeProto
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition: flow.c:230
AppLayerProtoDetectConfProtoDetectionEnabledDefault
int AppLayerProtoDetectConfProtoDetectionEnabledDefault(const char *ipproto, const char *alproto, bool default_enabled)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:2014
MpmCtx_
Definition: util-mpm.h:89
TcpSession_
Definition: stream-tcp-private.h:279
AppLayerProtoDetectProbingParser
struct AppLayerProtoDetectProbingParser_ AppLayerProtoDetectProbingParser
flow.h
SigIntId
#define SigIntId
Definition: suricata-common.h:304
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:458
SpmDestroyCtx
void SpmDestroyCtx(SpmCtx *ctx)
Definition: util-spm.c:183
AppLayerProtoDetectPMCtx_::min_len
uint16_t min_len
Definition: app-layer-detect-proto.c:125
AppLayerProtoDetectPrepareState
int AppLayerProtoDetectPrepareState(void)
Prepares the internal state for protocol detection. This needs to be called once all the patterns and...
Definition: app-layer-detect-proto.c:1648
FLOW_SET_PE_DONE
#define FLOW_SET_PE_DONE(f, dir)
Definition: flow.h:283
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
AppLayerProtoDetectCtx_::ctx_pp
AppLayerProtoDetectProbingParser * ctx_pp
Definition: app-layer-detect-proto.c:156
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-pool.h
AppLayerProtoDetectPPTestDataElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:2977
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
MpmAddPatternCI
int MpmAddPatternCI(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:253
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290
AppLayerProtoDetectConfProtoDetectionEnabled
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:2079
AppLayerProtoDetectPPTestDataPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:2987
SpmInitCtx
SpmCtx * SpmInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:173
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:124
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:771
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
PmqSetup
int PmqSetup(PrefilterRuleStore *pmq)
Setup a pmq.
Definition: util-prefilter.c:37
ALPROTO_NFS
@ ALPROTO_NFS
Definition: app-layer-protos.h:45
AppLayerProtoDetectProbingParser_::port
AppLayerProtoDetectProbingParserPort * port
Definition: app-layer-detect-proto.c:106
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1000
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2999
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2206
AppLayerProtoDetectProbingParserPort_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:92
app-layer.h
AppLayerProtoDetectCtxIpproto
struct AppLayerProtoDetectCtxIpproto_ AppLayerProtoDetectCtxIpproto
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:38
SpmThreadCtx_
Definition: util-spm.h:54
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:468
AppLayerProtoDetectPPTestDataElement_
Definition: app-layer-detect-proto.c:2974