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