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