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 
698  if (unlikely(p == NULL)) {
699  exit(EXIT_FAILURE);
700  }
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 
719  if (unlikely(p == NULL)) {
720  exit(EXIT_FAILURE);
721  }
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 
760  SCReturnPtr(p, "AppLayerProtoDetectProbingParser");
761 }
762 
763 static void AppLayerProtoDetectProbingParserFree(AppLayerProtoDetectProbingParser *p)
764 {
765  SCEnter();
766 
768  while (pt != NULL) {
770  AppLayerProtoDetectProbingParserPortFree(pt);
771  pt = pt_next;
772  }
773 
774  SCFree(p);
775 
776  SCReturn;
777 }
778 
780 AppLayerProtoDetectProbingParserElementCreate(AppProto alproto,
781  uint16_t port,
782  uint16_t min_depth,
783  uint16_t max_depth)
784 {
785  AppLayerProtoDetectProbingParserElement *pe = AppLayerProtoDetectProbingParserElementAlloc();
786 
787  pe->alproto = alproto;
788  pe->port = port;
789  pe->alproto_mask = AppLayerProtoDetectProbingParserGetMask(alproto);
790  pe->min_depth = min_depth;
791  pe->max_depth = max_depth;
792  pe->next = NULL;
793 
794  if (max_depth != 0 && min_depth >= max_depth) {
795  SCLogError("Invalid arguments sent to "
796  "register the probing parser. min_depth >= max_depth");
797  goto error;
798  }
799  if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) {
800  SCLogError("Invalid arguments sent to register "
801  "the probing parser. Invalid alproto - %d",
802  alproto);
803  goto error;
804  }
805 
806  SCReturnPtr(pe, "AppLayerProtoDetectProbingParserElement");
807  error:
808  AppLayerProtoDetectProbingParserElementFree(pe);
809  SCReturnPtr(NULL, "AppLayerProtoDetectProbingParserElement");
810 }
811 
813 AppLayerProtoDetectProbingParserElementDuplicate(AppLayerProtoDetectProbingParserElement *pe)
814 {
815  SCEnter();
816 
817  AppLayerProtoDetectProbingParserElement *new_pe = AppLayerProtoDetectProbingParserElementAlloc();
818 
819  new_pe->alproto = pe->alproto;
820  new_pe->port = pe->port;
821  new_pe->alproto_mask = pe->alproto_mask;
822  new_pe->min_depth = pe->min_depth;
823  new_pe->max_depth = pe->max_depth;
824  new_pe->ProbingParserTs = pe->ProbingParserTs;
825  new_pe->ProbingParserTc = pe->ProbingParserTc;
826  new_pe->next = NULL;
827 
828  SCReturnPtr(new_pe, "AppLayerProtoDetectProbingParserElement");
829 }
830 
831 #ifdef DEBUG
832 static void AppLayerProtoDetectPrintProbingParsers(AppLayerProtoDetectProbingParser *pp)
833 {
834  SCEnter();
835 
836  AppLayerProtoDetectProbingParserPort *pp_port = NULL;
838 
839  printf("\nProtocol Detection Configuration\n");
840 
841  for ( ; pp != NULL; pp = pp->next) {
842  /* print ip protocol */
843  if (pp->ipproto == IPPROTO_TCP)
844  printf("IPProto: TCP\n");
845  else if (pp->ipproto == IPPROTO_UDP)
846  printf("IPProto: UDP\n");
847  else
848  printf("IPProto: %"PRIu8"\n", pp->ipproto);
849 
850  pp_port = pp->port;
851  for ( ; pp_port != NULL; pp_port = pp_port->next) {
852  if (pp_port->dp != NULL) {
853  printf(" Port: %"PRIu16 "\n", pp_port->port);
854 
855  printf(" Destination port: (max-depth: %"PRIu16 ", "
856  "mask - %"PRIu32")\n",
857  pp_port->dp_max_depth,
858  pp_port->alproto_mask);
859  pp_pe = pp_port->dp;
860  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
861 
862  printf(" alproto: %s\n", AppProtoToString(pp_pe->alproto));
863  printf(" port: %"PRIu16 "\n", pp_pe->port);
864  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
865  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
866  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
867 
868  printf("\n");
869  }
870  }
871 
872  if (pp_port->sp == NULL) {
873  continue;
874  }
875 
876  printf(" Source port: (max-depth: %"PRIu16 ", "
877  "mask - %"PRIu32")\n",
878  pp_port->sp_max_depth,
879  pp_port->alproto_mask);
880  pp_pe = pp_port->sp;
881  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
882 
883  printf(" alproto: %s\n", AppProtoToString(pp_pe->alproto));
884  printf(" port: %"PRIu16 "\n", pp_pe->port);
885  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
886  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
887  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
888 
889  printf("\n");
890  }
891  }
892  }
893 
894  SCReturn;
895 }
896 #endif
897 
898 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
900 {
901  SCEnter();
902 
903  if (*head_pe == NULL) {
904  *head_pe = new_pe;
905  goto end;
906  }
907 
908  if ((*head_pe)->port == 0) {
909  if (new_pe->port != 0) {
910  new_pe->next = *head_pe;
911  *head_pe = new_pe;
912  } else {
913  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
914  while (temp_pe->next != NULL)
915  temp_pe = temp_pe->next;
916  temp_pe->next = new_pe;
917  }
918  } else {
919  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
920  if (new_pe->port == 0) {
921  while (temp_pe->next != NULL)
922  temp_pe = temp_pe->next;
923  temp_pe->next = new_pe;
924  } else {
925  while (temp_pe->next != NULL && temp_pe->next->port != 0)
926  temp_pe = temp_pe->next;
927  new_pe->next = temp_pe->next;
928  temp_pe->next = new_pe;
929 
930  }
931  }
932 
933  end:
934  SCReturn;
935 }
936 
937 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
939 {
940  SCEnter();
941 
942  if (*head_pp == NULL) {
943  *head_pp = new_pp;
944  goto end;
945  }
946 
947  AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
948  while (temp_pp->next != NULL)
949  temp_pp = temp_pp->next;
950  temp_pp->next = new_pp;
951 
952  end:
953  SCReturn;
954 }
955 
956 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
958 {
959  SCEnter();
960 
961  if (*head_port == NULL) {
962  *head_port = new_port;
963  goto end;
964  }
965 
966  if ((*head_port)->port == 0) {
967  new_port->next = *head_port;
968  *head_port = new_port;
969  } else {
970  AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
971  while (temp_port->next != NULL && temp_port->next->port != 0) {
972  temp_port = temp_port->next;
973  }
974  new_port->next = temp_port->next;
975  temp_port->next = new_port;
976  }
977 
978  end:
979  SCReturn;
980 }
981 
982 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
983  uint8_t ipproto,
984  uint16_t port,
985  AppProto alproto,
986  uint16_t min_depth, uint16_t max_depth,
987  uint8_t direction,
988  ProbingParserFPtr ProbingParser1,
989  ProbingParserFPtr ProbingParser2)
990 {
991  SCEnter();
992 
993  /* get the top level ipproto pp */
994  AppLayerProtoDetectProbingParser *curr_pp = *pp;
995  while (curr_pp != NULL) {
996  if (curr_pp->ipproto == ipproto)
997  break;
998  curr_pp = curr_pp->next;
999  }
1000  if (curr_pp == NULL) {
1001  AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1002  new_pp->ipproto = ipproto;
1003  AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1004  curr_pp = new_pp;
1005  }
1006 
1007  /* get the top level port pp */
1008  AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
1009  while (curr_port != NULL) {
1010  if (curr_port->port == port)
1011  break;
1012  curr_port = curr_port->next;
1013  }
1014  if (curr_port == NULL) {
1015  AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
1016  new_port->port = port;
1017  AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
1018  curr_port = new_port;
1019  if (direction & STREAM_TOSERVER) {
1020  curr_port->dp_max_depth = max_depth;
1021  } else {
1022  curr_port->sp_max_depth = max_depth;
1023  }
1024 
1026 
1027  zero_port = curr_pp->port;
1028  while (zero_port != NULL && zero_port->port != 0) {
1029  zero_port = zero_port->next;
1030  }
1031  if (zero_port != NULL) {
1033 
1034  zero_pe = zero_port->dp;
1035  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1036  if (curr_port->dp == NULL)
1037  curr_port->dp_max_depth = zero_pe->max_depth;
1038  if (zero_pe->max_depth == 0)
1039  curr_port->dp_max_depth = zero_pe->max_depth;
1040  if (curr_port->dp_max_depth != 0 &&
1041  curr_port->dp_max_depth < zero_pe->max_depth) {
1042  curr_port->dp_max_depth = zero_pe->max_depth;
1043  }
1044 
1046  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1047  AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1048  curr_port->alproto_mask |= dup_pe->alproto_mask;
1049  }
1050 
1051  zero_pe = zero_port->sp;
1052  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1053  if (curr_port->sp == NULL)
1054  curr_port->sp_max_depth = zero_pe->max_depth;
1055  if (zero_pe->max_depth == 0)
1056  curr_port->sp_max_depth = zero_pe->max_depth;
1057  if (curr_port->sp_max_depth != 0 &&
1058  curr_port->sp_max_depth < zero_pe->max_depth) {
1059  curr_port->sp_max_depth = zero_pe->max_depth;
1060  }
1061 
1063  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1064  AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1065  curr_port->alproto_mask |= dup_pe->alproto_mask;
1066  }
1067  } /* if (zero_port != NULL) */
1068  } /* if (curr_port == NULL) */
1069 
1070  /* insert the pe_pp */
1072  if (direction & STREAM_TOSERVER)
1073  curr_pe = curr_port->dp;
1074  else
1075  curr_pe = curr_port->sp;
1076  while (curr_pe != NULL) {
1077  if (curr_pe->alproto == alproto) {
1078  SCLogError("Duplicate pp registered - "
1079  "ipproto - %" PRIu8 " Port - %" PRIu16 " "
1080  "App Protocol - NULL, App Protocol(ID) - "
1081  "%" PRIu16 " min_depth - %" PRIu16 " "
1082  "max_dept - %" PRIu16 ".",
1083  ipproto, port, alproto, min_depth, max_depth);
1084  goto error;
1085  }
1086  curr_pe = curr_pe->next;
1087  }
1088  /* Get a new parser element */
1090  AppLayerProtoDetectProbingParserElementCreate(alproto,
1091  curr_port->port,
1092  min_depth, max_depth);
1093  if (new_pe == NULL)
1094  goto error;
1095  curr_pe = new_pe;
1097  if (direction & STREAM_TOSERVER) {
1098  curr_pe->ProbingParserTs = ProbingParser1;
1099  curr_pe->ProbingParserTc = ProbingParser2;
1100  if (curr_port->dp == NULL)
1101  curr_port->dp_max_depth = new_pe->max_depth;
1102  if (new_pe->max_depth == 0)
1103  curr_port->dp_max_depth = new_pe->max_depth;
1104  if (curr_port->dp_max_depth != 0 &&
1105  curr_port->dp_max_depth < new_pe->max_depth) {
1106  curr_port->dp_max_depth = new_pe->max_depth;
1107  }
1108  curr_port->alproto_mask |= new_pe->alproto_mask;
1109  head_pe = &curr_port->dp;
1110  } else {
1111  curr_pe->ProbingParserTs = ProbingParser2;
1112  curr_pe->ProbingParserTc = ProbingParser1;
1113  if (curr_port->sp == NULL)
1114  curr_port->sp_max_depth = new_pe->max_depth;
1115  if (new_pe->max_depth == 0)
1116  curr_port->sp_max_depth = new_pe->max_depth;
1117  if (curr_port->sp_max_depth != 0 &&
1118  curr_port->sp_max_depth < new_pe->max_depth) {
1119  curr_port->sp_max_depth = new_pe->max_depth;
1120  }
1121  curr_port->alproto_mask |= new_pe->alproto_mask;
1122  head_pe = &curr_port->sp;
1123  }
1124  AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1125 
1126  if (curr_port->port == 0) {
1127  AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
1128  while (temp_port != NULL && temp_port->port != 0) {
1129  if (direction & STREAM_TOSERVER) {
1130  if (temp_port->dp == NULL)
1131  temp_port->dp_max_depth = curr_pe->max_depth;
1132  if (curr_pe->max_depth == 0)
1133  temp_port->dp_max_depth = curr_pe->max_depth;
1134  if (temp_port->dp_max_depth != 0 &&
1135  temp_port->dp_max_depth < curr_pe->max_depth) {
1136  temp_port->dp_max_depth = curr_pe->max_depth;
1137  }
1138  AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1139  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1140  temp_port->alproto_mask |= curr_pe->alproto_mask;
1141  } else {
1142  if (temp_port->sp == NULL)
1143  temp_port->sp_max_depth = curr_pe->max_depth;
1144  if (curr_pe->max_depth == 0)
1145  temp_port->sp_max_depth = curr_pe->max_depth;
1146  if (temp_port->sp_max_depth != 0 &&
1147  temp_port->sp_max_depth < curr_pe->max_depth) {
1148  temp_port->sp_max_depth = curr_pe->max_depth;
1149  }
1150  AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1151  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1152  temp_port->alproto_mask |= curr_pe->alproto_mask;
1153  }
1154  temp_port = temp_port->next;
1155  } /* while */
1156  } /* if */
1157 
1158  error:
1159  SCReturn;
1160 }
1161 
1162 /***** Static Internal Calls: PM registration *****/
1163 
1164 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1165  uint8_t *ipprotos)
1166 {
1167  SCEnter();
1168 
1169  for (uint8_t i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1170  uint8_t ipproto = FlowGetReverseProtoMapping(i);
1171  for (int j = 0; j < 2; j++) {
1172  AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1173 
1174  for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1175  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1176  if (s->alproto == alproto)
1177  ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1178  }
1179  }
1180  }
1181 
1182  SCReturn;
1183 }
1184 
1185 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1186 {
1187  SCEnter();
1188 
1189  typedef struct TempContainer_ {
1190  PatIntId id;
1191  uint16_t content_len;
1192  uint8_t *content;
1193  } TempContainer;
1194 
1196  uint32_t struct_total_size = 0;
1197  uint32_t content_total_size = 0;
1198  /* array hash buffer */
1199  uint8_t *ahb = NULL;
1200  uint8_t *content = NULL;
1201  uint16_t content_len = 0;
1202  PatIntId max_id = 0;
1203  TempContainer *struct_offset = NULL;
1204  uint8_t *content_offset = NULL;
1205  int ret = 0;
1206 
1207  if (ctx->head == NULL)
1208  goto end;
1209 
1210  for (s = ctx->head; s != NULL; s = s->next) {
1211  struct_total_size += sizeof(TempContainer);
1212  content_total_size += s->cd->content_len;
1213  ctx->max_sig_id++;
1214  }
1215 
1216  ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1217  if (unlikely(ahb == NULL))
1218  goto error;
1219 
1220  struct_offset = (TempContainer *)ahb;
1221  content_offset = ahb + struct_total_size;
1222  for (s = ctx->head; s != NULL; s = s->next) {
1223  TempContainer *tcdup = (TempContainer *)ahb;
1224  content = s->cd->content;
1225  content_len = s->cd->content_len;
1226 
1227  for (; tcdup != struct_offset; tcdup++) {
1228  if (tcdup->content_len != content_len ||
1229  SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1230  {
1231  continue;
1232  }
1233  break;
1234  }
1235 
1236  if (tcdup != struct_offset) {
1237  s->cd->id = tcdup->id;
1238  continue;
1239  }
1240 
1241  struct_offset->content_len = content_len;
1242  struct_offset->content = content_offset;
1243  content_offset += content_len;
1244  memcpy(struct_offset->content, content, content_len);
1245  struct_offset->id = max_id++;
1246  s->cd->id = struct_offset->id;
1247 
1248  struct_offset++;
1249  }
1250 
1251  ctx->max_pat_id = max_id;
1252 
1253  goto end;
1254  error:
1255  ret = -1;
1256  end:
1257  if (ahb != NULL)
1258  SCFree(ahb);
1259  SCReturnInt(ret);
1260 }
1261 
1262 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1263 {
1264  SCEnter();
1265 
1266  int ret = 0;
1267  AppLayerProtoDetectPMSignature *s, *next_s;
1268  int mpm_ret;
1269  SigIntId id = 0;
1270 
1271  ctx->map = SCCalloc(ctx->max_sig_id, sizeof(AppLayerProtoDetectPMSignature *));
1272  if (ctx->map == NULL)
1273  goto error;
1274 
1275  /* add an array indexed by rule id to look up the sig */
1276  for (s = ctx->head; s != NULL; ) {
1277  next_s = s->next;
1278  s->id = id++;
1279  SCLogDebug("s->id %u offset %u depth %u",
1280  s->id, s->cd->offset, s->cd->depth);
1281 
1282  if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1283  mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1284  s->cd->content, s->cd->content_len,
1285  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1286  if (mpm_ret < 0)
1287  goto error;
1288  } else {
1289  mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1290  s->cd->content, s->cd->content_len,
1291  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1292  if (mpm_ret < 0)
1293  goto error;
1294  }
1295 
1296  ctx->map[s->id] = s;
1297  s->next = NULL;
1298  s = next_s;
1299  }
1300  ctx->head = NULL;
1301 
1302  goto end;
1303  error:
1304  ret = -1;
1305  end:
1306  SCReturnInt(ret);
1307 }
1308 
1309 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1310 {
1311  SCEnter();
1312 
1313  int ret = 0;
1314  MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1315 
1316  if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1317  goto error;
1318 
1319  goto end;
1320  error:
1321  ret = -1;
1322  end:
1323  SCReturnInt(ret);
1324 }
1325 
1326 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1327 {
1328  SCEnter();
1329  if (sig == NULL)
1330  SCReturn;
1331  if (sig->cd)
1332  DetectContentFree(NULL, sig->cd);
1333  SCFree(sig);
1334  SCReturn;
1335 }
1336 
1337 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
1338  AppProto alproto, uint8_t direction,
1339  ProbingParserFPtr PPFunc,
1340  uint16_t pp_min_depth, uint16_t pp_max_depth)
1341 {
1342  SCEnter();
1343 
1344  AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1345  if (unlikely(s == NULL))
1346  SCReturnInt(-1);
1347 
1348  s->alproto = alproto;
1349  s->direction = direction;
1350  s->cd = cd;
1351  s->PPFunc = PPFunc;
1352  s->pp_min_depth = pp_min_depth;
1353  s->pp_max_depth = pp_max_depth;
1354 
1355  /* prepend to the list */
1356  s->next = ctx->head;
1357  ctx->head = s;
1358 
1359  SCReturnInt(0);
1360 }
1361 
1362 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1363  const char *pattern,
1364  uint16_t depth, uint16_t offset,
1365  uint8_t direction,
1366  uint8_t is_cs,
1367  ProbingParserFPtr PPFunc,
1368  uint16_t pp_min_depth, uint16_t pp_max_depth)
1369 {
1370  SCEnter();
1371 
1372  AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1373  AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1374  int ret = 0;
1375 
1377  alpd_ctx.spm_global_thread_ctx, pattern);
1378  if (cd == NULL)
1379  goto error;
1380  cd->depth = depth;
1381  cd->offset = offset;
1382  if (!is_cs) {
1383  /* Rebuild as nocase */
1384  SpmDestroyCtx(cd->spm_ctx);
1385  cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1386  alpd_ctx.spm_global_thread_ctx);
1387  if (cd->spm_ctx == NULL) {
1388  goto error;
1389  }
1391  }
1392  if (depth < cd->content_len)
1393  goto error;
1394 
1395  if (direction & STREAM_TOSERVER)
1396  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1397  else
1398  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1399 
1400  if (pp_max_depth > ctx_pm->pp_max_len)
1401  ctx_pm->pp_max_len = pp_max_depth;
1402  if (depth < ctx_pm->min_len)
1403  ctx_pm->min_len = depth;
1404 
1405  /* Finally turn it into a signature and add to the ctx. */
1406  AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1407  PPFunc, pp_min_depth, pp_max_depth);
1408 
1409  goto end;
1410  error:
1411  DetectContentFree(NULL, cd);
1412  ret = -1;
1413  end:
1414  SCReturnInt(ret);
1415 }
1416 
1417 /***** Protocol Retrieval *****/
1418 
1420  const uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t flags, bool *reverse_flow)
1421 {
1422  SCEnter();
1423  SCLogDebug("buflen %u for %s direction", buflen,
1424  (flags & STREAM_TOSERVER) ? "toserver" : "toclient");
1425 
1426  AppProto alproto = ALPROTO_UNKNOWN;
1427  AppProto pm_alproto = ALPROTO_UNKNOWN;
1428 
1429  if (!FLOW_IS_PM_DONE(f, flags)) {
1430  AppProto pm_results[ALPROTO_MAX];
1431  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(
1432  tctx, f, buf, buflen, flags, pm_results, reverse_flow);
1433  if (pm_matches > 0) {
1434  DEBUG_VALIDATE_BUG_ON(pm_matches > 1);
1435  alproto = pm_results[0];
1436 
1437  // rerun probing parser for other direction if it is unknown
1438  uint8_t reverse_dir = (flags & STREAM_TOSERVER) ? STREAM_TOCLIENT : STREAM_TOSERVER;
1439  if (FLOW_IS_PP_DONE(f, reverse_dir)) {
1440  AppProto rev_alproto = (flags & STREAM_TOSERVER) ? f->alproto_tc : f->alproto_ts;
1441  if (rev_alproto == ALPROTO_UNKNOWN) {
1442  FLOW_RESET_PP_DONE(f, reverse_dir);
1443  }
1444  }
1445 
1446  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1447  * to avoid misdetecting DNS as DCERPC. */
1448  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1449  goto end;
1450 
1451  pm_alproto = alproto;
1452 
1453  /* fall through */
1454  }
1455  }
1456 
1457  if (!FLOW_IS_PP_DONE(f, flags)) {
1458  bool rflow = false;
1459  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow);
1460  if (AppProtoIsValid(alproto)) {
1461  if (rflow) {
1462  *reverse_flow = true;
1463  }
1464  goto end;
1465  }
1466  }
1467 
1468  /* Look if flow can be found in expectation list */
1469  if (!FLOW_IS_PE_DONE(f, flags)) {
1470  alproto = AppLayerProtoDetectPEGetProto(f, ipproto, flags);
1471  }
1472 
1473  end:
1474  if (!AppProtoIsValid(alproto))
1475  alproto = pm_alproto;
1476 
1477  SCReturnUInt(alproto);
1478 }
1479 
1480 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1481 {
1482  SCEnter();
1483 
1484  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1485 
1486  if (pp == NULL)
1487  goto end;
1488 
1489  while (pp != NULL) {
1490  tmp_pp = pp->next;
1491  AppLayerProtoDetectProbingParserFree(pp);
1492  pp = tmp_pp;
1493  }
1494 
1495  end:
1496  SCReturn;
1497 }
1498 
1499 static void AppLayerProtoDetectFreeAliases(void)
1500 {
1501  SCEnter();
1502 
1503  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1504  if (cur_alias == NULL)
1505  goto end;
1506 
1507  AppLayerProtoDetectAliases *next_alias = NULL;
1508  while (cur_alias != NULL) {
1509  next_alias = cur_alias->next;
1510  SCFree(cur_alias);
1511  cur_alias = next_alias;
1512  }
1513 
1514  alpda_ctx = NULL;
1515 
1516 end:
1517  SCReturn;
1518 }
1519 
1520 /***** State Preparation *****/
1521 
1523 {
1524  SCEnter();
1525 
1526  AppLayerProtoDetectPMCtx *ctx_pm;
1527  int i, j;
1528  int ret = 0;
1529 
1530  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1531  for (j = 0; j < 2; j++) {
1532  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1533 
1534  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1535  goto error;
1536 
1537  if (ctx_pm->max_sig_id == 0)
1538  continue;
1539 
1540  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1541  goto error;
1542  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1543  goto error;
1544  }
1545  }
1546 
1547 #ifdef DEBUG
1548  if (SCLogDebugEnabled()) {
1549  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1550  }
1551 #endif
1552 
1553  goto end;
1554  error:
1555  ret = -1;
1556  end:
1557  SCReturnInt(ret);
1558 }
1559 
1560 /***** PP registration *****/
1561 
1562 /** \brief register parser at a port
1563  *
1564  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1565  */
1566 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1567  const char *portstr,
1568  AppProto alproto,
1569  uint16_t min_depth, uint16_t max_depth,
1570  uint8_t direction,
1571  ProbingParserFPtr ProbingParser1,
1572  ProbingParserFPtr ProbingParser2)
1573 {
1574  SCEnter();
1575 
1576  DetectPort *head = NULL;
1577  DetectPortParse(NULL,&head, portstr);
1578  DetectPort *temp_dp = head;
1579  while (temp_dp != NULL) {
1580  uint16_t port = temp_dp->port;
1581  if (port == 0 && temp_dp->port2 != 0)
1582  port++;
1583  for (;;) {
1584  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1585  ipproto,
1586  port,
1587  alproto,
1588  min_depth, max_depth,
1589  direction,
1590  ProbingParser1,
1591  ProbingParser2);
1592  if (port == temp_dp->port2) {
1593  break;
1594  } else {
1595  port++;
1596  }
1597  }
1598  temp_dp = temp_dp->next;
1599  }
1601 
1602  SCReturn;
1603 }
1604 
1605 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1606  uint8_t ipproto,
1607  const char *alproto_name,
1608  AppProto alproto,
1609  uint16_t min_depth, uint16_t max_depth,
1610  ProbingParserFPtr ProbingParserTs,
1611  ProbingParserFPtr ProbingParserTc)
1612 {
1613  SCEnter();
1614 
1615  char param[100];
1616  int r;
1617  ConfNode *node;
1618  ConfNode *port_node = NULL;
1619  int config = 0;
1620 
1621  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1622  alproto_name, ".detection-ports");
1623  if (r < 0) {
1624  FatalError("snprintf failure.");
1625  } else if (r > (int)sizeof(param)) {
1626  FatalError("buffer not big enough to write param.");
1627  }
1628  node = ConfGetNode(param);
1629  if (node == NULL) {
1630  SCLogDebug("Entry for %s not found.", param);
1631  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1632  alproto_name, ".", ipproto_name, ".detection-ports");
1633  if (r < 0) {
1634  FatalError("snprintf failure.");
1635  } else if (r > (int)sizeof(param)) {
1636  FatalError("buffer not big enough to write param.");
1637  }
1638  node = ConfGetNode(param);
1639  if (node == NULL)
1640  goto end;
1641  }
1642 
1643  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1644  port_node = ConfNodeLookupChild(node, "dp");
1645  if (port_node == NULL)
1646  port_node = ConfNodeLookupChild(node, "toserver");
1647 
1648  if (port_node != NULL && port_node->val != NULL) {
1650  port_node->val,
1651  alproto,
1652  min_depth, max_depth,
1653  STREAM_TOSERVER, /* to indicate dp */
1654  ProbingParserTs, ProbingParserTc);
1655  }
1656 
1657  /* detect by source port of flow */
1658  port_node = ConfNodeLookupChild(node, "sp");
1659  if (port_node == NULL)
1660  port_node = ConfNodeLookupChild(node, "toclient");
1661 
1662  if (port_node != NULL && port_node->val != NULL) {
1664  port_node->val,
1665  alproto,
1666  min_depth, max_depth,
1667  STREAM_TOCLIENT, /* to indicate sp */
1668  ProbingParserTc, ProbingParserTs);
1669 
1670  }
1671 
1672  config = 1;
1673  end:
1674  SCReturnInt(config);
1675 }
1676 
1677 /***** PM registration *****/
1678 
1680  const char *pattern,
1681  uint16_t depth, uint16_t offset,
1682  uint8_t direction)
1683 {
1684  SCEnter();
1685  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1686  pattern, depth, offset,
1687  direction, 1 /* case-sensitive */,
1688  NULL, 0, 0);
1689  SCReturnInt(r);
1690 }
1691 
1693  const char *pattern, uint16_t depth, uint16_t offset,
1694  uint8_t direction,
1695  ProbingParserFPtr PPFunc,
1696  uint16_t pp_min_depth, uint16_t pp_max_depth)
1697 {
1698  SCEnter();
1699  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1700  pattern, depth, offset,
1701  direction, 1 /* case-sensitive */,
1702  PPFunc, pp_min_depth, pp_max_depth);
1703  SCReturnInt(r);
1704 }
1705 
1707  const char *pattern,
1708  uint16_t depth, uint16_t offset,
1709  uint8_t direction)
1710 {
1711  SCEnter();
1712  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1713  pattern, depth, offset,
1714  direction, 0 /* !case-sensitive */,
1715  NULL, 0, 0);
1716  SCReturnInt(r);
1717 }
1718 
1719 /***** Setup/General Registration *****/
1720 
1722 {
1723  SCEnter();
1724 
1725  int i, j;
1726 
1727  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1728 
1729  uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1730  uint8_t mpm_matcher = PatternMatchDefaultMatcher();
1731 
1732  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1733  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1734  FatalError("Unable to alloc SpmGlobalThreadCtx.");
1735  }
1736 
1737  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1738  for (j = 0; j < 2; j++) {
1739  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1740  }
1741  }
1742 
1744 
1745  SCReturnInt(0);
1746 }
1747 
1748 /**
1749  * \todo incomplete. Need more work.
1750  */
1752 {
1753  SCEnter();
1754 
1755  int ipproto_map = 0;
1756  int dir = 0;
1757  PatIntId id = 0;
1758  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1759  AppLayerProtoDetectPMSignature *sig = NULL;
1760 
1761  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1762  for (dir = 0; dir < 2; dir++) {
1763  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1764  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1765  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1766  sig = pm_ctx->map[id];
1767  AppLayerProtoDetectPMFreeSignature(sig);
1768  }
1769  SCFree(pm_ctx->map);
1770  pm_ctx->map = NULL;
1771  }
1772  }
1773 
1775 
1776  AppLayerProtoDetectFreeAliases();
1777 
1778  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1779 
1780  SCReturnInt(0);
1781 }
1782 
1783 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1784 {
1785  SCEnter();
1786 
1787  if (alpd_ctx.alproto_names[alproto] == NULL)
1788  alpd_ctx.alproto_names[alproto] = alproto_name;
1789 
1790  SCReturn;
1791 }
1792 
1793 void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
1794 {
1795  SCEnter();
1796 
1798  if (unlikely(new_alias == NULL)) {
1799  exit(EXIT_FAILURE);
1800  }
1801 
1802  new_alias->proto_name = proto_name;
1803  new_alias->proto_alias = proto_alias;
1804  new_alias->next = NULL;
1805 
1806  if (alpda_ctx == NULL) {
1807  alpda_ctx = new_alias;
1808  } else {
1809  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1810  while (cur_alias->next != NULL) {
1811  cur_alias = cur_alias->next;
1812  }
1813  cur_alias->next = new_alias;
1814  }
1815 
1816  SCReturn;
1817 }
1818 
1819 /** \brief request applayer to wrap up this protocol and rerun protocol
1820  * detection.
1821  *
1822  * When this is called, the old session is reset unconditionally. A
1823  * 'detect/log' flush packet is generated for both direction before
1824  * the reset, so allow for final detection and logging.
1825  *
1826  * \param f flow to act on
1827  * \param dp destination port to use in protocol detection. Set to 443
1828  * for start tls, set to the HTTP uri port for CONNECT and
1829  * set to 0 to not use it.
1830  * \param expect_proto expected protocol. AppLayer event will be set if
1831  * detected protocol differs from this.
1832  */
1833 bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1834 {
1835  if (FlowChangeProto(f)) {
1836  // If we are already changing protocols, from SMTP to TLS for instance,
1837  // and that we do not get TLS but HTTP1, which is requesting change to HTTP2,
1838  // we do not proceed the new protocol change
1839  return false;
1840  }
1842  f->protodetect_dp = dp;
1843  f->alproto_expect = expect_proto;
1845  f->alproto_orig = f->alproto;
1846  // If one side is unknown yet, set it to the other known side
1847  if (f->alproto_ts == ALPROTO_UNKNOWN) {
1848  f->alproto_ts = f->alproto;
1849  }
1850  if (f->alproto_tc == ALPROTO_UNKNOWN) {
1851  f->alproto_tc = f->alproto;
1852  }
1853  return true;
1854 }
1855 
1856 /** \brief request applayer to wrap up this protocol and rerun protocol
1857  * detection with expectation of TLS. Used by STARTTLS.
1858  *
1859  * Sets detection port to 443 to make port based TLS detection work for
1860  * SMTP, FTP etc as well.
1861  *
1862  * \param f flow to act on
1863  */
1865 {
1867 }
1868 
1870 {
1871  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1872  FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1873  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1874  FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1875  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1876  FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1879 
1880  // Does not free the structures for the parser
1881  // keeps f->alstate for new state creation
1882  f->alparser = NULL;
1883  f->alproto = ALPROTO_UNKNOWN;
1886 }
1887 
1889  const char *ipproto, const char *alproto, bool default_enabled)
1890 {
1891  SCEnter();
1892 
1893  BUG_ON(ipproto == NULL || alproto == NULL);
1894 
1895  int enabled = 1;
1896  char param[100];
1897  ConfNode *node;
1898  int r;
1899 
1900  if (RunmodeIsUnittests())
1901  goto enabled;
1902 
1903 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1904  // so that fuzzig takes place for DNP3 and such
1905  default_enabled = true;
1906 #endif
1907 
1908  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1909  alproto, ".enabled");
1910  if (r < 0) {
1911  FatalError("snprintf failure.");
1912  } else if (r > (int)sizeof(param)) {
1913  FatalError("buffer not big enough to write param.");
1914  }
1915 
1916  node = ConfGetNode(param);
1917  if (node == NULL) {
1918  SCLogDebug("Entry for %s not found.", param);
1919  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1920  alproto, ".", ipproto, ".enabled");
1921  if (r < 0) {
1922  FatalError("snprintf failure.");
1923  } else if (r > (int)sizeof(param)) {
1924  FatalError("buffer not big enough to write param.");
1925  }
1926 
1927  node = ConfGetNode(param);
1928  if (node == NULL) {
1929  SCLogDebug("Entry for %s not found.", param);
1930  if (default_enabled) {
1931  goto enabled;
1932  } else {
1933  goto disabled;
1934  }
1935  }
1936  }
1937 
1938  if (node->val) {
1939  if (ConfValIsTrue(node->val)) {
1940  goto enabled;
1941  } else if (ConfValIsFalse(node->val)) {
1942  goto disabled;
1943  } else if (strcasecmp(node->val, "detection-only") == 0) {
1944  goto enabled;
1945  }
1946  }
1947 
1948  /* Invalid or null value. */
1949  SCLogError("Invalid value found for %s.", param);
1950  exit(EXIT_FAILURE);
1951 
1952  disabled:
1953  enabled = 0;
1954  enabled:
1955  SCReturnInt(enabled);
1956 }
1957 
1958 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
1959 {
1960  return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
1961 }
1962 
1964 {
1965  SCEnter();
1966 
1968  MpmCtx *mpm_ctx;
1969  MpmThreadCtx *mpm_tctx;
1970  int i, j;
1971  PatIntId max_pat_id = 0;
1972 
1973  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1974  for (j = 0; j < 2; j++) {
1975  if (max_pat_id == 0) {
1976  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1977 
1978  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1979  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1980  {
1981  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1982  }
1983  }
1984  }
1985 
1986  alpd_tctx = SCCalloc(1, sizeof(*alpd_tctx));
1987  if (alpd_tctx == NULL)
1988  goto error;
1989 
1990  /* Get the max pat id for all the mpm ctxs. */
1991  if (PmqSetup(&alpd_tctx->pmq) < 0)
1992  goto error;
1993 
1994  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1995  for (j = 0; j < 2; j++) {
1996  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1997  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1998  MpmInitThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
1999  }
2000  }
2001 
2003  if (alpd_tctx->spm_thread_ctx == NULL) {
2004  goto error;
2005  }
2006 
2007  goto end;
2008  error:
2009  if (alpd_tctx != NULL)
2011  alpd_tctx = NULL;
2012  end:
2013  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2014 }
2015 
2017 {
2018  SCEnter();
2019 
2020  MpmCtx *mpm_ctx;
2021  MpmThreadCtx *mpm_tctx;
2022  int ipproto_map, dir;
2023 
2024  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2025  for (dir = 0; dir < 2; dir++) {
2026  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2027  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2028  MpmDestroyThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2029  }
2030  }
2031  PmqFree(&alpd_tctx->pmq);
2032  if (alpd_tctx->spm_thread_ctx != NULL) {
2034  }
2035  SCFree(alpd_tctx);
2036 
2037  SCReturn;
2038 }
2039 
2040 /***** Utility *****/
2041 
2042 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2043 {
2044  SCEnter();
2045 
2046  // Custom case for only signature-only protocol so far
2047  if (alproto == ALPROTO_HTTP) {
2050  } else {
2051  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2052  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2053  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2054  }
2055 
2056  SCReturn;
2057 }
2058 
2060 {
2061  SCEnter();
2062 
2063  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2064  while (cur_alias != NULL) {
2065  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2066  alproto_name = cur_alias->proto_name;
2067  }
2068 
2069  cur_alias = cur_alias->next;
2070  }
2071 
2072  AppProto a;
2073  AppProto b = StringToAppProto(alproto_name);
2074  for (a = 0; a < ALPROTO_MAX; a++) {
2075  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2076  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2077  SCReturnCT(b, "AppProto");
2078  }
2079  }
2080 
2081  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2082 }
2083 
2085 {
2086  // Special case for http (any version) :
2087  // returns "http" if both versions are enabled
2088  // and returns "http1" or "http2" if only one version is enabled
2089  if (alproto == ALPROTO_HTTP) {
2090  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2091  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2092  return "http";
2093  } // else
2094  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2095  } // else
2096  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2097  }
2098  return alpd_ctx.alproto_names[alproto];
2099 }
2100 
2102 {
2103  SCEnter();
2104 
2105  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2106 
2107  int alproto;
2108 
2109  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2110  if (alpd_ctx.alproto_names[alproto] != NULL)
2111  alprotos[alproto] = 1;
2112  }
2113 
2114  SCReturn;
2115 }
2116 
2118 
2119 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2120  uint8_t *ipprotos)
2121 {
2122  if (expectation_proto[alproto] == IPPROTO_TCP) {
2123  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2124  }
2125  if (expectation_proto[alproto] == IPPROTO_UDP) {
2126  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2127  }
2128 }
2129 
2131 {
2132  if (expectation_proto[alproto]) {
2133  if (proto != expectation_proto[alproto]) {
2134  SCLogError("Expectation on 2 IP protocols are not supported");
2135  }
2136  }
2137  expectation_proto[alproto] = proto;
2138 }
2139 
2140 /***** Unittests *****/
2141 
2142 #ifdef UNITTESTS
2143 
2144 #include "app-layer-htp.h"
2145 #include "detect-engine-alert.h"
2146 
2147 static AppLayerProtoDetectCtx alpd_ctx_ut;
2148 
2150 {
2151  SCEnter();
2152  alpd_ctx_ut = alpd_ctx;
2153  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2154  SCReturn;
2155 }
2156 
2158 {
2159  SCEnter();
2160  alpd_ctx = alpd_ctx_ut;
2161  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2162  SCReturn;
2163 }
2164 
2165 static int AppLayerProtoDetectTest01(void)
2166 {
2169 
2170  const char *buf = "HTTP";
2171  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2172  buf = "GET";
2173  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2174 
2176  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2177  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2178 
2181  PASS;
2182 }
2183 
2184 static int AppLayerProtoDetectTest02(void)
2185 {
2188 
2189  const char *buf = "HTTP";
2190  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2191  buf = "ftp";
2192  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2193 
2195  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2196  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2197 
2198  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2199  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2200 
2203 
2206  PASS;
2207 }
2208 
2209 static int AppLayerProtoDetectTest03(void)
2210 {
2213 
2214  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2215  AppProto pm_results[ALPROTO_MAX];
2216  memset(pm_results, 0, sizeof(pm_results));
2217  Flow f;
2218  memset(&f, 0x00, sizeof(f));
2219  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2220 
2221 
2222  const char *buf = "HTTP";
2223  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2224  buf = "220 ";
2225  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2226 
2228  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2229  * it sets internal structures which depends on the above function. */
2232 
2233  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2234  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2235  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2236  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2239 
2240  bool rflow = false;
2241  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2242  &f, l7data, sizeof(l7data),
2243  STREAM_TOCLIENT,
2244  pm_results, &rflow);
2245  FAIL_IF(cnt != 1);
2246  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2247 
2251  PASS;
2252 }
2253 
2254 static int AppLayerProtoDetectTest04(void)
2255 {
2258 
2259  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2260  Flow f;
2261  memset(&f, 0x00, sizeof(f));
2262  AppProto pm_results[ALPROTO_MAX];
2263  memset(pm_results, 0, sizeof(pm_results));
2264  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2265 
2266  const char *buf = "200 ";
2267  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2268 
2270  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2271  * it sets internal structures which depends on the above function. */
2274 
2275  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2276  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2277  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2278  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2280 
2281  bool rdir = false;
2282  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2283  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2284  pm_results, &rdir);
2285  FAIL_IF(cnt != 1);
2286  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2287 
2291  PASS;
2292 }
2293 
2294 static int AppLayerProtoDetectTest05(void)
2295 {
2298 
2299  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2300  AppProto pm_results[ALPROTO_MAX];
2301  memset(pm_results, 0, sizeof(pm_results));
2302  Flow f;
2303  memset(&f, 0x00, sizeof(f));
2304  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2305 
2306  const char *buf = "HTTP";
2307  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2308  buf = "220 ";
2309  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2310 
2312  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2313  * it sets internal structures which depends on the above function. */
2316 
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  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2320  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2323 
2324  bool rdir = false;
2325  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2326  &f, l7data, sizeof(l7data),
2327  STREAM_TOCLIENT,
2328  pm_results, &rdir);
2329  FAIL_IF(cnt != 1);
2330  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2331 
2335  PASS;
2336 }
2337 
2338 static int AppLayerProtoDetectTest06(void)
2339 {
2342 
2343  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2344  AppProto pm_results[ALPROTO_MAX];
2345  memset(pm_results, 0, sizeof(pm_results));
2346  Flow f;
2347  memset(&f, 0x00, sizeof(f));
2348  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2349 
2350  const char *buf = "HTTP";
2351  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2352  buf = "220 ";
2353  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2354 
2356  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2357  * it sets internal structures which depends on the above function. */
2360 
2361  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2362  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2363  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2364  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2367 
2368  bool rdir = false;
2369  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2370  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2371  pm_results, &rdir);
2372  FAIL_IF(cnt != 1);
2373  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2374 
2378  PASS;
2379 }
2380 
2381 static int AppLayerProtoDetectTest07(void)
2382 {
2385 
2386  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2387  Flow f;
2388  memset(&f, 0x00, sizeof(f));
2389  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2390  AppProto pm_results[ALPROTO_MAX];
2391  memset(pm_results, 0, sizeof(pm_results));
2392 
2393  const char *buf = "HTTP";
2394  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2395 
2397  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2398  * it sets internal structures which depends on the above function. */
2400 
2401  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2402  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2403  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2404  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2406 
2407  bool rdir = false;
2408  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2409  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2410  pm_results, &rdir);
2411  FAIL_IF(cnt != 0);
2412 
2416  PASS;
2417 }
2418 
2419 static int AppLayerProtoDetectTest08(void)
2420 {
2423 
2424  uint8_t l7data[] = {
2425  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2426  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2427  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2428  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2429  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2430  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2431  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2432  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2433  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2434  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2435  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2436  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2437  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2438  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2439  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2440  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2441  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2442  0x00
2443  };
2444  AppProto pm_results[ALPROTO_MAX];
2445  memset(pm_results, 0, sizeof(pm_results));
2446  Flow f;
2447  memset(&f, 0x00, sizeof(f));
2448  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2449 
2450  const char *buf = "|ff|SMB";
2451  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2452 
2454  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2455  * it sets internal structures which depends on the above function. */
2458 
2459  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2460  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2461  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2462  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2464 
2465  bool rdir = false;
2466  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2467  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2468  pm_results, &rdir);
2469  FAIL_IF(cnt != 1);
2470  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2471 
2475  PASS;
2476 }
2477 
2478 static int AppLayerProtoDetectTest09(void)
2479 {
2482 
2483  uint8_t l7data[] = {
2484  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2485  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2486  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2487  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2488  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2489  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2490  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2491  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2492  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2493  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2494  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2495  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2496  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2497  0x00, 0x02, 0x02
2498  };
2499  AppProto pm_results[ALPROTO_MAX];
2500  memset(pm_results, 0, sizeof(pm_results));
2501  Flow f;
2502  memset(&f, 0x00, sizeof(f));
2503  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2504 
2505  const char *buf = "|fe|SMB";
2506  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2507 
2509  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2510  * it sets internal structures which depends on the above function. */
2513 
2514  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2515  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2516  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2517  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2519 
2520  bool rdir = false;
2521  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2522  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2523  pm_results, &rdir);
2524  FAIL_IF(cnt != 1);
2525  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2526 
2530  PASS;
2531 }
2532 
2533 static int AppLayerProtoDetectTest10(void)
2534 {
2537 
2538  uint8_t l7data[] = {
2539  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2540  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2541  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2542  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2543  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2544  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2545  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2546  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2547  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2548  };
2549  AppProto pm_results[ALPROTO_MAX];
2550  memset(pm_results, 0, sizeof(pm_results));
2551  Flow f;
2552  memset(&f, 0x00, sizeof(f));
2553  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2554 
2555  const char *buf = "|05 00|";
2556  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2557 
2559  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2560  * it sets internal structures which depends on the above function. */
2563 
2564  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2565  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2566  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2567  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2569 
2570  bool rdir = false;
2571  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2572  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2573  pm_results, &rdir);
2574  FAIL_IF(cnt != 1);
2575  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2576 
2580  PASS;
2581 }
2582 
2583 /**
2584  * \test Why we still get http for connect... obviously because
2585  * we also match on the reply, duh
2586  */
2587 static int AppLayerProtoDetectTest11(void)
2588 {
2591 
2592  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2593  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2594  AppProto pm_results[ALPROTO_MAX];
2595  memset(pm_results, 0, sizeof(pm_results));
2596  Flow f;
2597  memset(&f, 0x00, sizeof(f));
2598  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2599 
2601  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2603  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2605  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2607  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2609  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2611  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2613  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2615  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2616 
2618  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2619  * it sets internal structures which depends on the above function. */
2622 
2623  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2624  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2625  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2626  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2627 
2636 
2637  bool rdir = false;
2638  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2639  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2640  pm_results, &rdir);
2641  FAIL_IF(cnt != 1);
2642  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2643 
2644  memset(pm_results, 0, sizeof(pm_results));
2645  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2646  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2647  pm_results, &rdir);
2648  FAIL_IF(cnt != 1);
2649  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2650 
2654  PASS;
2655 }
2656 
2657 /**
2658  * \test AlpProtoSignature test
2659  */
2660 static int AppLayerProtoDetectTest12(void)
2661 {
2664 
2665  int r = 0;
2666 
2668  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2669  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2670  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2671  {
2672  printf("failure 1\n");
2673  goto end;
2674  }
2675 
2677  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2678  printf("failure 2\n");
2679  goto end;
2680  }
2681  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2682  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2683  {
2684  printf("failure 3\n");
2685  goto end;
2686  }
2687  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2688  printf("failure 4\n");
2689  goto end;
2690  }
2691  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2692  printf("failure 5\n");
2693  goto end;
2694  }
2695  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2696  printf("failure 6\n");
2697  goto end;
2698  }
2699 
2700  r = 1;
2701 
2702  end:
2705  return r;
2706 }
2707 
2708 /**
2709  * \test What about if we add some sigs only for udp but call for tcp?
2710  * It should not detect any proto
2711  */
2712 static int AppLayerProtoDetectTest13(void)
2713 {
2716 
2717  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2718  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2719  AppProto pm_results[ALPROTO_MAX];
2720 
2721  Flow f;
2722  memset(&f, 0x00, sizeof(f));
2723  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2724 
2726  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2728  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2730  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2732  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2734  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2736  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2738  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2740  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2741 
2743  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2744  * it sets internal structures which depends on the above function. */
2746 
2747  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2748  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2749 
2758 
2759  memset(pm_results, 0, sizeof(pm_results));
2760  bool rdir = false;
2761  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2762  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2763  pm_results, &rdir);
2764  FAIL_IF(cnt != 0);
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 != 0);
2771 
2775  PASS;
2776 }
2777 
2778 /**
2779  * \test What about if we add some sigs only for udp calling it for UDP?
2780  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2781  * to ensure that TCP/UDP differences work correctly.
2782  */
2783 static int AppLayerProtoDetectTest14(void)
2784 {
2787 
2788  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2789  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2790  AppProto pm_results[ALPROTO_MAX];
2791  uint32_t cnt;
2792  Flow f;
2793  memset(&f, 0x00, sizeof(f));
2794  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2795 
2797  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2799  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2801  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2803  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2805  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2807  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2809  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2811  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2812 
2814  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2815  * it sets internal structures which depends on the above function. */
2818 
2819  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2820  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2821 
2830 
2831  memset(pm_results, 0, sizeof(pm_results));
2832  bool rdir = false;
2833  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2834  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2835  pm_results, &rdir);
2836  FAIL_IF(cnt != 1);
2837  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2838 
2839  memset(pm_results, 0, sizeof(pm_results));
2840  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2841  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2842  pm_results, &rdir);
2843  FAIL_IF(cnt != 1);
2844  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2845 
2849  PASS;
2850 }
2851 
2853  const char *alproto_name;
2855  uint16_t port;
2856  uint32_t alproto_mask;
2857  uint32_t min_depth;
2858  uint32_t max_depth;
2860 
2862  uint16_t port;
2863  uint32_t alproto_mask;
2864  uint16_t dp_max_depth;
2865  uint16_t sp_max_depth;
2866 
2872 
2873 
2875  uint8_t ipproto;
2876 
2880 
2881 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2883  int no_of_ip_proto)
2884 {
2885  int result = 0;
2886  int i = -1, j = -1 , k = -1;
2887 #ifdef DEBUG
2888  int dir = 0;
2889 #endif
2890  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2891  if (pp->ipproto != ip_proto[i].ipproto)
2892  goto end;
2893 
2895  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2896  if (pp_port->port != ip_proto[i].port[k].port)
2897  goto end;
2898  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2899  goto end;
2900  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2901  goto end;
2902  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2903  goto end;
2904  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2905  goto end;
2906 
2907  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2908 #ifdef DEBUG
2909  dir = 0;
2910 #endif
2911  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2912  j++, pp_element = pp_element->next) {
2913 
2914  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2915  goto end;
2916  }
2917  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
2918  goto end;
2919  }
2920  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2921  goto end;
2922  }
2923  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2924  goto end;
2925  }
2926  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2927  goto end;
2928  }
2929  } /* for */
2930  if (pp_element != NULL)
2931  goto end;
2932 
2933  pp_element = pp_port->sp;
2934 #ifdef DEBUG
2935  dir = 1;
2936 #endif
2937  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2938  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2939  goto end;
2940  }
2941  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
2942  goto end;
2943  }
2944  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2945  goto end;
2946  }
2947  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2948  goto end;
2949  }
2950  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2951  goto end;
2952  }
2953  } /* for */
2954  if (pp_element != NULL)
2955  goto end;
2956  }
2957  if (pp_port != NULL)
2958  goto end;
2959  }
2960  if (pp != NULL)
2961  goto end;
2962 
2963  result = 1;
2964  end:
2965 #ifdef DEBUG
2966  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2967 #endif
2968  return result;
2969 }
2970 
2971 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2972  const uint8_t *input,
2973  uint32_t input_len, uint8_t *rdir)
2974 {
2975  return 0;
2976 }
2977 
2978 static int AppLayerProtoDetectTest15(void)
2979 {
2982 
2983  int result = 0;
2984 
2985  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
2986  ProbingParserDummyForTesting, NULL);
2987  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2988  "80",
2989  ALPROTO_SMB,
2990  5, 6,
2991  STREAM_TOSERVER,
2992  ProbingParserDummyForTesting, NULL);
2993  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2994  "80",
2995  ALPROTO_FTP,
2996  7, 10,
2997  STREAM_TOSERVER,
2998  ProbingParserDummyForTesting, NULL);
2999 
3000  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3001  "81",
3003  9, 10,
3004  STREAM_TOSERVER,
3005  ProbingParserDummyForTesting, NULL);
3006  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3007  "81",
3008  ALPROTO_FTP,
3009  7, 15,
3010  STREAM_TOSERVER,
3011  ProbingParserDummyForTesting, NULL);
3012  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3013  "0",
3014  ALPROTO_SMTP,
3015  12, 0,
3016  STREAM_TOSERVER,
3017  ProbingParserDummyForTesting, NULL);
3018  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3019  "0",
3020  ALPROTO_TLS,
3021  12, 18,
3022  STREAM_TOSERVER,
3023  ProbingParserDummyForTesting, NULL);
3024 
3025  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3026  "85",
3028  9, 10,
3029  STREAM_TOSERVER,
3030  ProbingParserDummyForTesting, NULL);
3031  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3032  "85",
3033  ALPROTO_FTP,
3034  7, 15,
3035  STREAM_TOSERVER,
3036  ProbingParserDummyForTesting, NULL);
3037  result = 1;
3038 
3039  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3040  "85",
3041  ALPROTO_IMAP,
3042  12, 23,
3043  STREAM_TOSERVER,
3044  ProbingParserDummyForTesting, NULL);
3045 
3046  /* toclient */
3047  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3048  "0",
3050  12, 23,
3051  STREAM_TOCLIENT,
3052  ProbingParserDummyForTesting, NULL);
3053  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3054  "0",
3055  ALPROTO_IRC,
3056  12, 14,
3057  STREAM_TOCLIENT,
3058  ProbingParserDummyForTesting, NULL);
3059 
3060  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3061  "85",
3063  9, 10,
3064  STREAM_TOCLIENT,
3065  ProbingParserDummyForTesting, NULL);
3066  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3067  "81",
3068  ALPROTO_FTP,
3069  7, 15,
3070  STREAM_TOCLIENT,
3071  ProbingParserDummyForTesting, NULL);
3072  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3073  "0",
3074  ALPROTO_TLS,
3075  12, 18,
3076  STREAM_TOCLIENT,
3077  ProbingParserDummyForTesting, NULL);
3078  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3079  ProbingParserDummyForTesting, NULL);
3080  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3081  "81",
3083  9, 10,
3084  STREAM_TOCLIENT,
3085  ProbingParserDummyForTesting, NULL);
3086  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3087  "90",
3088  ALPROTO_FTP,
3089  7, 15,
3090  STREAM_TOCLIENT,
3091  ProbingParserDummyForTesting, NULL);
3092  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3093  "80",
3094  ALPROTO_SMB,
3095  5, 6,
3096  STREAM_TOCLIENT,
3097  ProbingParserDummyForTesting, NULL);
3098  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3099  "85",
3100  ALPROTO_IMAP,
3101  12, 23,
3102  STREAM_TOCLIENT,
3103  ProbingParserDummyForTesting, NULL);
3104  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3105  "0",
3106  ALPROTO_SMTP,
3107  12, 17,
3108  STREAM_TOCLIENT,
3109  ProbingParserDummyForTesting, NULL);
3110  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3111  "80",
3112  ALPROTO_FTP,
3113  7, 10,
3114  STREAM_TOCLIENT,
3115  ProbingParserDummyForTesting, NULL);
3116 
3117  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3118  { "http", ALPROTO_HTTP1, 80, 1 << ALPROTO_HTTP1, 5, 8 },
3119  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3120  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3121  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3122  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3123  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3124  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3125  };
3126  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80,
3127  1 << ALPROTO_HTTP1, 5, 8 },
3128  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3129  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3130  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3131  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3132  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3133  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 } };
3134 
3135  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3136  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3137  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3138  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3139  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3140  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3141  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3142  };
3143  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3144  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3145  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3146  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3147  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3148  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3149  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3150  };
3151 
3152  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3153  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3154  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3155  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3156  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3157  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3158  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3159  };
3160  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3161  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3162  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3163  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3164  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3165  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3166  };
3167 
3168  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3169  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3170  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3171  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3172  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3173  };
3174  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3175  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3176  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3177  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3178  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3179  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3180  };
3181 
3182  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3183  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3184  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3185  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3186  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3187  };
3188  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3189  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3190  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3191  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3192  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3193  };
3194 
3195 
3196  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3197  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3198  };
3199  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3200  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3201  };
3202 
3203  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3204  {
3205  80,
3206  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3207  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3208  (1 << ALPROTO_JABBER)),
3209  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3210  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3211  (1 << ALPROTO_SMTP)),
3212  23,
3213  element_ts_80,
3214  element_tc_80,
3215  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3216  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3217  },
3218  {
3219  81,
3220  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3221  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3222  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) |
3223  (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3224  23,
3225  element_ts_81,
3226  element_tc_81,
3227  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3228  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3229  },
3230  { 85,
3231  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3232  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3233  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3234  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3235  23, element_ts_85, element_tc_85,
3236  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3237  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3238  { 90,
3239  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3240  (1 << ALPROTO_JABBER)),
3241  ((1 << ALPROTO_FTP) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3242  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3243  23, element_ts_90, element_tc_90,
3244  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3245  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3246  { 0,
3247  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3248  (1 << ALPROTO_JABBER)),
3249  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3250  (1 << ALPROTO_SMTP)),
3251  23, element_ts_0, element_tc_0,
3252  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3253  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3254  };
3255 
3256  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3257  { 85,
3258  (1 << ALPROTO_IMAP),
3259  (1 << ALPROTO_IMAP),
3260  23,
3261  element_ts_85_udp, element_tc_85_udp,
3262  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3263  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3264  },
3265  };
3266 
3268  { IPPROTO_TCP,
3269  ports_tcp,
3270  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3271  },
3272  { IPPROTO_UDP,
3273  ports_udp,
3274  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3275  },
3276  };
3277 
3278 
3279  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3280  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3281  goto end;
3282  }
3283  result = 1;
3284 
3285  end:
3288  return result;
3289 }
3290 
3291 
3292 /** \test test if the engine detect the proto and match with it */
3293 static int AppLayerProtoDetectTest16(void)
3294 {
3295  int result = 0;
3296  Flow *f = NULL;
3297  HtpState *http_state = NULL;
3298  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3299  "User-Agent: Mozilla/1.0\r\n"
3300  "Cookie: hellocatch\r\n\r\n";
3301  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3302  TcpSession ssn;
3303  Packet *p = NULL;
3304  Signature *s = NULL;
3305  ThreadVars tv;
3306  DetectEngineThreadCtx *det_ctx = NULL;
3307  DetectEngineCtx *de_ctx = NULL;
3309 
3310  memset(&tv, 0, sizeof(ThreadVars));
3311  memset(&ssn, 0, sizeof(TcpSession));
3312 
3313  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3314  if (p == NULL) {
3315  printf("packet setup failed: ");
3316  goto end;
3317  }
3318 
3319  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3320  if (f == NULL) {
3321  printf("flow setup failed: ");
3322  goto end;
3323  }
3324  f->protoctx = &ssn;
3325  f->proto = IPPROTO_TCP;
3326  p->flow = f;
3327 
3331 
3332  f->alproto = ALPROTO_HTTP1;
3333 
3334  StreamTcpInitConfig(true);
3335 
3337  if (de_ctx == NULL) {
3338  goto end;
3339  }
3340  de_ctx->flags |= DE_QUIET;
3341 
3342  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3343  "(msg:\"Test content option\"; "
3344  "sid:1;)");
3345  if (s == NULL) {
3346  goto end;
3347  }
3348 
3350  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3351 
3352  int r = AppLayerParserParse(
3353  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3354  if (r != 0) {
3355  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3356  goto end;
3357  }
3358 
3359  http_state = f->alstate;
3360  if (http_state == NULL) {
3361  printf("no http state: ");
3362  goto end;
3363  }
3364 
3365  /* do detect */
3366  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3367 
3368  if (!PacketAlertCheck(p, 1)) {
3369  printf("sig 1 didn't alert, but it should: ");
3370  goto end;
3371  }
3372  result = 1;
3373  end:
3374  if (alp_tctx != NULL)
3376  if (det_ctx != NULL)
3377  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3378  if (de_ctx != NULL)
3380  if (de_ctx != NULL)
3382 
3383  StreamTcpFreeConfig(true);
3384 
3385  UTHFreePackets(&p, 1);
3386  UTHFreeFlow(f);
3387  return result;
3388 }
3389 
3390 /** \test test if the engine detect the proto on a non standar port
3391  * and match with it */
3392 static int AppLayerProtoDetectTest17(void)
3393 {
3394  int result = 0;
3395  Flow *f = NULL;
3396  HtpState *http_state = NULL;
3397  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3398  "User-Agent: Mozilla/1.0\r\n"
3399  "Cookie: hellocatch\r\n\r\n";
3400  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3401  TcpSession ssn;
3402  Packet *p = NULL;
3403  Signature *s = NULL;
3404  ThreadVars tv;
3405  DetectEngineThreadCtx *det_ctx = NULL;
3406  DetectEngineCtx *de_ctx = NULL;
3408 
3409  memset(&tv, 0, sizeof(ThreadVars));
3410  memset(&ssn, 0, sizeof(TcpSession));
3411 
3412  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3413 
3414  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3415  if (f == NULL)
3416  goto end;
3417  f->protoctx = &ssn;
3418  f->proto = IPPROTO_TCP;
3419  p->flow = f;
3423  f->alproto = ALPROTO_HTTP1;
3424 
3425  StreamTcpInitConfig(true);
3426 
3428  if (de_ctx == NULL) {
3429  goto end;
3430  }
3431  de_ctx->flags |= DE_QUIET;
3432 
3433  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3434  "(msg:\"http over non standar port\"; "
3435  "sid:1;)");
3436  if (s == NULL) {
3437  goto end;
3438  }
3439 
3441  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3442 
3443  int r = AppLayerParserParse(
3444  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3445  if (r != 0) {
3446  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3447  goto end;
3448  }
3449 
3450  http_state = f->alstate;
3451  if (http_state == NULL) {
3452  printf("no http state: ");
3453  goto end;
3454  }
3455 
3456  /* do detect */
3457  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3458 
3459  if (!PacketAlertCheck(p, 1)) {
3460  printf("sig 1 didn't alert, but it should: ");
3461  goto end;
3462  }
3463 
3464  result = 1;
3465 
3466  end:
3467  if (alp_tctx != NULL)
3469  if (det_ctx != NULL)
3470  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3471  if (de_ctx != NULL)
3473  if (de_ctx != NULL)
3475 
3476  StreamTcpFreeConfig(true);
3477 
3478  UTHFreePackets(&p, 1);
3479  UTHFreeFlow(f);
3480  return result;
3481 }
3482 
3483 /** \test test if the engine detect the proto and doesn't match
3484  * because the sig expects another proto (ex ftp)*/
3485 static int AppLayerProtoDetectTest18(void)
3486 {
3487  int result = 0;
3488  Flow *f = NULL;
3489  HtpState *http_state = NULL;
3490  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3491  "User-Agent: Mozilla/1.0\r\n"
3492  "Cookie: hellocatch\r\n\r\n";
3493  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3494  TcpSession ssn;
3495  Packet *p = NULL;
3496  Signature *s = NULL;
3497  ThreadVars tv;
3498  DetectEngineThreadCtx *det_ctx = NULL;
3499  DetectEngineCtx *de_ctx = NULL;
3501 
3502  memset(&tv, 0, sizeof(ThreadVars));
3503  memset(&ssn, 0, sizeof(TcpSession));
3504 
3505  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3506 
3507  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3508  if (f == NULL)
3509  goto end;
3510  f->protoctx = &ssn;
3511  f->proto = IPPROTO_TCP;
3512  p->flow = f;
3516  f->alproto = ALPROTO_HTTP1;
3517 
3518  StreamTcpInitConfig(true);
3519 
3521  if (de_ctx == NULL) {
3522  goto end;
3523  }
3524  de_ctx->flags |= DE_QUIET;
3525 
3526  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3527  "(msg:\"Test content option\"; "
3528  "sid:1;)");
3529  if (s == NULL) {
3530  goto end;
3531  }
3532 
3534  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3535 
3536  int r = AppLayerParserParse(
3537  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3538  if (r != 0) {
3539  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3540  goto end;
3541  }
3542 
3543  http_state = f->alstate;
3544  if (http_state == NULL) {
3545  printf("no http state: ");
3546  goto end;
3547  }
3548 
3549  /* do detect */
3550  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3551 
3552  if (PacketAlertCheck(p, 1)) {
3553  printf("sig 1 alerted, but it should not (it's not ftp): ");
3554  goto end;
3555  }
3556 
3557  result = 1;
3558  end:
3559  if (alp_tctx != NULL)
3561  if (det_ctx != NULL)
3562  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3563  if (de_ctx != NULL)
3565  if (de_ctx != NULL)
3567 
3568  StreamTcpFreeConfig(true);
3569 
3570  UTHFreePackets(&p, 1);
3571  UTHFreeFlow(f);
3572  return result;
3573 }
3574 
3575 /** \test test if the engine detect the proto and doesn't match
3576  * because the packet has another proto (ex ftp) */
3577 static int AppLayerProtoDetectTest19(void)
3578 {
3579  int result = 0;
3580  Flow *f = NULL;
3581  uint8_t http_buf1[] = "MPUT one\r\n";
3582  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3583  TcpSession ssn;
3584  Packet *p = NULL;
3585  Signature *s = NULL;
3586  ThreadVars tv;
3587  DetectEngineThreadCtx *det_ctx = NULL;
3588  DetectEngineCtx *de_ctx = NULL;
3590 
3591  memset(&tv, 0, sizeof(ThreadVars));
3592  memset(&ssn, 0, sizeof(TcpSession));
3593 
3594  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3595 
3596  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3597  if (f == NULL)
3598  goto end;
3599  f->protoctx = &ssn;
3600  f->proto = IPPROTO_TCP;
3601  p->flow = f;
3605  f->alproto = ALPROTO_FTP;
3606 
3607  StreamTcpInitConfig(true);
3608 
3610  if (de_ctx == NULL) {
3611  goto end;
3612  }
3613  de_ctx->flags |= DE_QUIET;
3614 
3615  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3616  "(msg:\"http over non standar port\"; "
3617  "sid:1;)");
3618  if (s == NULL) {
3619  goto end;
3620  }
3621 
3623  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3624 
3625  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3626  STREAM_TOSERVER, http_buf1, http_buf1_len);
3627  if (r != 0) {
3628  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3629  goto end;
3630  }
3631 
3632  /* do detect */
3633  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3634 
3635  if (PacketAlertCheck(p, 1)) {
3636  printf("sig 1 alerted, but it should not (it's ftp): ");
3637  goto end;
3638  }
3639 
3640  result = 1;
3641 
3642  end:
3643  if (alp_tctx != NULL)
3645  if (det_ctx != NULL)
3646  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3647  if (de_ctx != NULL)
3649  if (de_ctx != NULL)
3651 
3652  StreamTcpFreeConfig(true);
3653  UTHFreePackets(&p, 1);
3654  UTHFreeFlow(f);
3655  return result;
3656 }
3657 
3659 {
3660  SCEnter();
3661 
3662  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3663  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3664  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3665  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3666  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3667  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3668  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3669  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3670  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3671  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3672  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3673  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3674  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3675  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3676  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3677  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3678  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3679  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3680  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3681 
3682  SCReturn;
3683 }
3684 
3685 #endif /* UNITTESTS */
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:196
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2861
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:281
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:2157
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
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:1605
detect-content.h
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:90
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:1721
AppLayerProtoDetectProbingParser_::next
struct AppLayerProtoDetectProbingParser_ * next
Definition: app-layer-detect-proto.c:108
FlowSetChangeProtoFlag
void FlowSetChangeProtoFlag(Flow *f)
Set flag to indicate to change proto for the flow.
Definition: flow.c:214
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:1706
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1018
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SinglePatternMatchDefaultMatcher
uint8_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
ALPROTO_DCERPC
@ ALPROTO_DCERPC
Definition: app-layer-protos.h:38
FLOW_IS_PE_DONE
#define FLOW_IS_PE_DONE(f, dir)
Definition: flow.h:274
flow-util.h
AppLayerExpectationSetup
void AppLayerExpectationSetup(void)
Definition: app-layer-expectation.c:146
FLOW_SET_PM_DONE
#define FLOW_SET_PM_DONE(f, dir)
Definition: flow.h:276
AppLayerProtoDetectProbingParserElement_::min_depth
uint16_t min_depth
Definition: app-layer-detect-proto.c:75
MpmThreadCtx_
Definition: util-mpm.h:46
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
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:1864
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:215
AppLayerProtoDetectProbingParserPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:90
Flow_::proto
uint8_t proto
Definition: flow.h:372
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
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:473
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:350
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2149
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2853
Flow_::protomap
uint8_t protomap
Definition: flow.h:444
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:74
ALPROTO_IRC
@ ALPROTO_IRC
Definition: app-layer-protos.h:39
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:836
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:455
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2580
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2042
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:1833
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:312
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:222
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:321
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:228
ALPROTO_FTP
@ ALPROTO_FTP
Definition: app-layer-protos.h:31
AppLayerProtoDetectPPTestDataElement_::min_depth
uint32_t min_depth
Definition: app-layer-detect-proto.c:2857
PatIntId
#define PatIntId
Definition: suricata-common.h:318
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:338
AppLayerProtoDetectPPTestDataElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:2854
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1884
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:93
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:455
AppLayerProtoDetectPMSignature_
Definition: app-layer-detect-proto.c:111
MpmCtx_::maxdepth
uint16_t maxdepth
Definition: util-mpm.h:94
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:467
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:440
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:216
DetectContentFree
void DetectContentFree(DetectEngineCtx *de_ctx, void *ptr)
this function will SCFree memory associated with DetectContentData
Definition: detect-content.c:372
AppLayerProtoDetectPPTestDataElement_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2856
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:111
HtpState_
Definition: app-layer-htp.h:244
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:537
FLOW_SET_PP_DONE
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:277
util-unittest-helper.h
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2874
util-memcmp.h
FLOW_IS_PM_DONE
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:272
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
Definition: util-mpm.c:210
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:1566
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_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:69
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:474
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:501
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:2117
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:1182
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:426
decode.h
MpmDestroyThreadCtx
void MpmDestroyThreadCtx(MpmThreadCtx *mpm_thread_ctx, const uint16_t matcher)
Definition: util-mpm.c:203
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint8_t matcher)
Definition: util-spm.c:138
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:273
DetectEngineThreadCtx_
Definition: detect.h:1092
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:94
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:1869
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:1692
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2867
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:2314
DetectPort_
Port structure for detection engine.
Definition: detect.h:214
AppLayerProtoDetectProbingParserPort_
Definition: app-layer-detect-proto.c:88
DetectContentData_::id
PatIntId id
Definition: detect-content.h:105
app-layer-parser.h
AppLayerProtoDetectPPTestDataIPProto_::no_of_port
int no_of_port
Definition: app-layer-detect-proto.c:2878
AppLayerProtoDetectCtx_
The app layer protocol detection context.
Definition: app-layer-detect-proto.c:147
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
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:2211
SCReturn
#define SCReturn
Definition: util-debug.h:273
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:280
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
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:97
AppLayerProtoDetectPPTestDataPort_::toclient_element
AppLayerProtoDetectPPTestDataElement * toclient_element
Definition: app-layer-detect-proto.c:2868
Packet_
Definition: decode.h:436
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:170
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:168
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:104
AppLayerProtoDetectPMCtx_::head
AppLayerProtoDetectPMSignature * head
Definition: app-layer-detect-proto.c:132
AppLayerRegisterExpectationProto
void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
Definition: app-layer-detect-proto.c:2130
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2870
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:166
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:1783
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_HTTP2
@ ALPROTO_HTTP2
Definition: app-layer-protos.h:61
AppLayerProtoDetectPPTestDataPort_::dp_max_depth
uint16_t dp_max_depth
Definition: app-layer-detect-proto.c:2864
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:418
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:2862
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:168
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:250
Flow_::alproto_expect
AppProto alproto_expect
Definition: flow.h:458
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:252
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:2142
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:417
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:506
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:291
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:786
AppLayerProtoDetectAliases_
Definition: app-layer-detect-proto.c:164
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
Packet_::flow
struct Flow_ * flow
Definition: decode.h:475
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:3291
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:68
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:690
AppLayerProtoDetectPPTestDataPort_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2863
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:1303
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3501
AppLayerProtoDetectAliases_::next
struct AppLayerProtoDetectAliases_ * next
Definition: app-layer-detect-proto.c:167
AppLayerProtoDetectPPTestDataIPProto_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:2875
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:97
AppLayerProtoDetectPMSignature
struct AppLayerProtoDetectPMSignature_ AppLayerProtoDetectPMSignature
FLOW_RESET_PE_DONE
#define FLOW_RESET_PE_DONE(f, dir)
Definition: flow.h:282
AppLayerProtoDetectDeSetup
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
Definition: app-layer-detect-proto.c:1751
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
SWAP_VARS
#define SWAP_VARS(type, a, b)
Definition: suricata-common.h:428
AppLayerProtoDetectPMSignature_::id
SigIntId id
Definition: app-layer-detect-proto.c:114
util-spm.h
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
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:829
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:844
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:111
AppLayerProtoDetectSupportedAppProtocols
void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
Definition: app-layer-detect-proto.c:2101
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:1419
AppLayerProtoDetectUnittestsRegister
void AppLayerProtoDetectUnittestsRegister(void)
Register unittests for app layer proto detection module.
Definition: app-layer-detect-proto.c:3658
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:2858
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1963
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2059
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:450
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:475
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:593
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:562
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
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:224
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2541
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
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:1793
AppLayerProtoDetectThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: app-layer-detect-proto.c:174
app-layer-protos.h
AppLayerProtoDetectProbingParser_
Definition: app-layer-detect-proto.c:104
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:71
AppLayerProtoDetectPPTestDataPort_::ts_no_of_element
int ts_no_of_element
Definition: app-layer-detect-proto.c:2869
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:95
AppLayerProtoDetectPPTestDataPort
struct AppLayerProtoDetectPPTestDataPort_ AppLayerProtoDetectPPTestDataPort
AppLayerProtoDetectDestroyCtxThread
void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
Destroys the app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:2016
AppLayerProtoDetectProbingParserElement_::port
uint16_t port
Definition: app-layer-detect-proto.c:71
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:838
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:65
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:1679
FlowChangeProto
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition: flow.c:233
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:1888
MpmCtx_
Definition: util-mpm.h:88
TcpSession_
Definition: stream-tcp-private.h:283
AppLayerProtoDetectProbingParser
struct AppLayerProtoDetectProbingParser_ AppLayerProtoDetectProbingParser
flow.h
SigIntId
#define SigIntId
Definition: suricata-common.h:315
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:451
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:1522
FLOW_SET_PE_DONE
#define FLOW_SET_PE_DONE(f, dir)
Definition: flow.h:278
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:449
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:2855
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:259
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:1958
AppLayerProtoDetectPPTestDataPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:2865
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:103
PmqSetup
int PmqSetup(PrefilterRuleStore *pmq)
Setup a pmq.
Definition: util-prefilter.c:37
AppLayerProtoDetectProbingParser_::port
AppLayerProtoDetectProbingParserPort * port
Definition: app-layer-detect-proto.c:106
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1015
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2877
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2084
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:469
AppLayerProtoDetectPPTestDataElement_
Definition: app-layer-detect-proto.c:2852