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