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  int enabled = 1;
1920  char param[100];
1921  SCConfNode *node;
1922  int r;
1923 
1924  if (RunmodeIsUnittests())
1925  goto enabled;
1926 
1927 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1928  // so that fuzzig takes place for DNP3 and such
1929  default_enabled = true;
1930 #endif
1931 
1932  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1933  alproto, ".enabled");
1934  if (r < 0) {
1935  FatalError("snprintf failure.");
1936  } else if (r > (int)sizeof(param)) {
1937  FatalError("buffer not big enough to write param.");
1938  }
1939 
1940  node = SCConfGetNode(param);
1941  if (node == NULL) {
1942  SCLogDebug("Entry for %s not found.", param);
1943  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1944  alproto, ".", ipproto, ".enabled");
1945  if (r < 0) {
1946  FatalError("snprintf failure.");
1947  } else if (r > (int)sizeof(param)) {
1948  FatalError("buffer not big enough to write param.");
1949  }
1950 
1951  node = SCConfGetNode(param);
1952  if (node == NULL) {
1953  SCLogDebug("Entry for %s not found.", param);
1954  if (default_enabled) {
1955  goto enabled;
1956  } else {
1957  goto disabled;
1958  }
1959  }
1960  }
1961 
1962  if (node->val) {
1963  if (SCConfValIsTrue(node->val)) {
1964  goto enabled;
1965  } else if (SCConfValIsFalse(node->val)) {
1966  goto disabled;
1967  } else if (strcasecmp(node->val, "detection-only") == 0) {
1968  goto enabled;
1969  }
1970  }
1971 
1972  /* Invalid or null value. */
1973  SCLogError("Invalid value found for %s.", param);
1974  exit(EXIT_FAILURE);
1975 
1976  disabled:
1977  enabled = 0;
1978  enabled:
1979  SCReturnInt(enabled);
1980 }
1981 
1982 int SCAppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
1983 {
1984  return SCAppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
1985 }
1986 
1988 {
1989  SCEnter();
1990 
1992  MpmCtx *mpm_ctx;
1993  MpmThreadCtx *mpm_tctx;
1994  int i, j;
1995  PatIntId max_pat_id = 0;
1996 
1997  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1998  for (j = 0; j < 2; j++) {
1999  if (max_pat_id == 0) {
2000  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2001 
2002  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
2003  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
2004  {
2005  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2006  }
2007  }
2008  }
2009 
2010  alpd_tctx = SCCalloc(1, sizeof(*alpd_tctx));
2011  if (alpd_tctx == NULL)
2012  goto error;
2013 
2014  /* Get the max pat id for all the mpm ctxs. */
2015  if (PmqSetup(&alpd_tctx->pmq) < 0)
2016  goto error;
2017 
2018  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2019  for (j = 0; j < 2; j++) {
2020  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
2021  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
2022  MpmInitThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2023  }
2024  }
2025 
2027  if (alpd_tctx->spm_thread_ctx == NULL) {
2028  goto error;
2029  }
2030 
2031  goto end;
2032  error:
2033  if (alpd_tctx != NULL)
2035  alpd_tctx = NULL;
2036  end:
2037  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2038 }
2039 
2041 {
2042  SCEnter();
2043 
2044  MpmCtx *mpm_ctx;
2045  MpmThreadCtx *mpm_tctx;
2046  int ipproto_map, dir;
2047 
2048  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2049  for (dir = 0; dir < 2; dir++) {
2050  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2051  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2052  MpmDestroyThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2053  }
2054  }
2055  PmqFree(&alpd_tctx->pmq);
2056  if (alpd_tctx->spm_thread_ctx != NULL) {
2058  }
2059  SCFree(alpd_tctx);
2060 
2061  SCReturn;
2062 }
2063 
2064 /***** Utility *****/
2065 
2066 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2067 {
2068  SCEnter();
2069 
2070  // Custom case for only signature-only protocol so far
2071  if (alproto == ALPROTO_HTTP) {
2074  } else if (alproto == ALPROTO_DOH2) {
2075  // DOH2 is not detected, just HTTP2
2077  } else {
2078  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2079  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2080  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2081  }
2082 
2083  SCReturn;
2084 }
2085 
2087 {
2088  SCEnter();
2089 
2090  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2091  while (cur_alias != NULL) {
2092  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2093  alproto_name = cur_alias->proto_name;
2094  }
2095 
2096  cur_alias = cur_alias->next;
2097  }
2098 
2099  AppProto a;
2100  AppProto b = StringToAppProto(alproto_name);
2101  for (a = 0; a < g_alproto_max; a++) {
2102  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2103  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2104  SCReturnCT(b, "AppProto");
2105  }
2106  }
2107 
2108  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2109 }
2110 
2112 {
2113  // Special case for http (any version) :
2114  // returns "http" if both versions are enabled
2115  // and returns "http1" or "http2" if only one version is enabled
2116  if (alproto == ALPROTO_HTTP) {
2117  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2118  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2119  return "http";
2120  } // else
2121  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2122  } // else
2123  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2124  }
2125  return alpd_ctx.alproto_names[alproto];
2126 }
2127 
2129 {
2130  SCEnter();
2131 
2132  memset(alprotos, 0, g_alproto_max * sizeof(AppProto));
2133 
2134  int alproto;
2135 
2136  for (alproto = 0; alproto != g_alproto_max; alproto++) {
2137  if (alpd_ctx.alproto_names[alproto] != NULL)
2138  alprotos[alproto] = 1;
2139  }
2140 
2141  SCReturn;
2142 }
2143 
2144 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2145  uint8_t *ipprotos)
2146 {
2147  if (alproto >= alpd_ctx.expectation_proto_len) {
2148  return;
2149  }
2150  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_TCP) {
2151  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2152  }
2153  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_UDP) {
2154  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2155  }
2156 }
2157 
2159 {
2160  if (alpd_ctx.expectation_proto[alproto]) {
2161  if (proto != alpd_ctx.expectation_proto[alproto]) {
2162  SCLogError("Expectation on 2 IP protocols are not supported");
2163  }
2164  }
2165  alpd_ctx.expectation_proto[alproto] = proto;
2166 }
2167 
2168 /***** Unittests *****/
2169 
2170 #ifdef UNITTESTS
2171 
2172 #include "app-layer-htp.h"
2173 #include "detect-engine-alert.h"
2174 
2175 static AppLayerProtoDetectCtx alpd_ctx_ut;
2176 
2178 {
2179  SCEnter();
2180  alpd_ctx_ut = alpd_ctx;
2181  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2182  SCReturn;
2183 }
2184 
2186 {
2187  SCEnter();
2188  alpd_ctx = alpd_ctx_ut;
2189  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2190  SCReturn;
2191 }
2192 
2193 static int AppLayerProtoDetectTest01(void)
2194 {
2197 
2198  const char *buf = "HTTP";
2200  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2201  buf = "GET";
2203  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2204 
2206  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2207  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2208 
2211  PASS;
2212 }
2213 
2214 static int AppLayerProtoDetectTest02(void)
2215 {
2218 
2219  const char *buf = "HTTP";
2221  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2222  buf = "ftp";
2223  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2224 
2226  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2227  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2228 
2229  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2230  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2231 
2234 
2237  PASS;
2238 }
2239 
2240 static int AppLayerProtoDetectTest03(void)
2241 {
2244 
2245  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2246  AppProto pm_results[g_alproto_max];
2247  memset(pm_results, 0, sizeof(pm_results));
2248  Flow f;
2249  memset(&f, 0x00, sizeof(f));
2250  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2251 
2252 
2253  const char *buf = "HTTP";
2255  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2256  buf = "220 ";
2257  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2258 
2260  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2261  * it sets internal structures which depends on the above function. */
2264 
2265  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2266  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2267  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2268  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2271 
2272  bool rflow = false;
2273  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2274  &f, l7data, sizeof(l7data),
2275  STREAM_TOCLIENT,
2276  pm_results, &rflow);
2277  FAIL_IF(cnt != 1);
2278  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2279 
2283  PASS;
2284 }
2285 
2286 static int AppLayerProtoDetectTest04(void)
2287 {
2290 
2291  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2292  Flow f;
2293  memset(&f, 0x00, sizeof(f));
2294  AppProto pm_results[g_alproto_max];
2295  memset(pm_results, 0, sizeof(pm_results));
2296  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2297 
2298  const char *buf = "200 ";
2300  IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2301 
2303  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2304  * it sets internal structures which depends on the above function. */
2307 
2308  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2309  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2310  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2311  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2313 
2314  bool rdir = false;
2315  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2316  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2317  pm_results, &rdir);
2318  FAIL_IF(cnt != 1);
2319  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2320 
2324  PASS;
2325 }
2326 
2327 static int AppLayerProtoDetectTest05(void)
2328 {
2331 
2332  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2333  AppProto pm_results[g_alproto_max];
2334  memset(pm_results, 0, sizeof(pm_results));
2335  Flow f;
2336  memset(&f, 0x00, sizeof(f));
2337  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2338 
2339  const char *buf = "HTTP";
2341  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2342  buf = "220 ";
2343  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2344 
2346  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2347  * it sets internal structures which depends on the above function. */
2350 
2351  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2352  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2353  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2354  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2357 
2358  bool rdir = false;
2359  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2360  &f, l7data, sizeof(l7data),
2361  STREAM_TOCLIENT,
2362  pm_results, &rdir);
2363  FAIL_IF(cnt != 1);
2364  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2365 
2369  PASS;
2370 }
2371 
2372 static int AppLayerProtoDetectTest06(void)
2373 {
2376 
2377  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2378  AppProto pm_results[g_alproto_max];
2379  memset(pm_results, 0, sizeof(pm_results));
2380  Flow f;
2381  memset(&f, 0x00, sizeof(f));
2382  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2383 
2384  const char *buf = "HTTP";
2386  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2387  buf = "220 ";
2388  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2389 
2391  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2392  * it sets internal structures which depends on the above function. */
2395 
2396  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2397  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2398  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2399  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2402 
2403  bool rdir = false;
2404  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2405  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2406  pm_results, &rdir);
2407  FAIL_IF(cnt != 1);
2408  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2409 
2413  PASS;
2414 }
2415 
2416 static int AppLayerProtoDetectTest07(void)
2417 {
2420 
2421  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2422  Flow f;
2423  memset(&f, 0x00, sizeof(f));
2424  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2425  AppProto pm_results[g_alproto_max];
2426  memset(pm_results, 0, sizeof(pm_results));
2427 
2428  const char *buf = "HTTP";
2430  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2431 
2433  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2434  * it sets internal structures which depends on the above function. */
2436 
2437  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2438  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2439  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2440  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2442 
2443  bool rdir = false;
2444  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2445  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2446  pm_results, &rdir);
2447  FAIL_IF(cnt != 0);
2448 
2452  PASS;
2453 }
2454 
2455 static int AppLayerProtoDetectTest08(void)
2456 {
2459 
2460  uint8_t l7data[] = {
2461  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2462  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2463  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2464  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2465  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2466  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2467  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2468  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2469  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2470  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2471  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2472  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2473  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2474  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2475  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2476  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2477  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2478  0x00
2479  };
2480  AppProto pm_results[g_alproto_max];
2481  memset(pm_results, 0, sizeof(pm_results));
2482  Flow f;
2483  memset(&f, 0x00, sizeof(f));
2484  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2485 
2486  const char *buf = "|ff|SMB";
2487  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2488 
2490  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2491  * it sets internal structures which depends on the above function. */
2494 
2495  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2496  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2497  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2498  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2500 
2501  bool rdir = false;
2502  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2503  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2504  pm_results, &rdir);
2505  FAIL_IF(cnt != 1);
2506  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2507 
2511  PASS;
2512 }
2513 
2514 static int AppLayerProtoDetectTest09(void)
2515 {
2518 
2519  uint8_t l7data[] = {
2520  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2521  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2522  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2523  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2524  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2525  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2526  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2527  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2528  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2529  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2530  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2531  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2532  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2533  0x00, 0x02, 0x02
2534  };
2535  AppProto pm_results[g_alproto_max];
2536  memset(pm_results, 0, sizeof(pm_results));
2537  Flow f;
2538  memset(&f, 0x00, sizeof(f));
2539  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2540 
2541  const char *buf = "|fe|SMB";
2542  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2543 
2545  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2546  * it sets internal structures which depends on the above function. */
2549 
2550  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2551  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2552  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2553  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2555 
2556  bool rdir = false;
2557  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2558  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2559  pm_results, &rdir);
2560  FAIL_IF(cnt != 1);
2561  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2562 
2566  PASS;
2567 }
2568 
2569 static int AppLayerProtoDetectTest10(void)
2570 {
2573 
2574  uint8_t l7data[] = {
2575  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2576  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2577  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2578  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2579  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2580  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2581  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2582  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2583  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2584  };
2585  AppProto pm_results[g_alproto_max];
2586  memset(pm_results, 0, sizeof(pm_results));
2587  Flow f;
2588  memset(&f, 0x00, sizeof(f));
2589  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2590 
2591  const char *buf = "|05 00|";
2593  IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2594 
2596  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2597  * it sets internal structures which depends on the above function. */
2600 
2601  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2602  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2603  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2604  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2606 
2607  bool rdir = false;
2608  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2609  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2610  pm_results, &rdir);
2611  FAIL_IF(cnt != 1);
2612  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2613 
2617  PASS;
2618 }
2619 
2620 /**
2621  * \test Why we still get http for connect... obviously because
2622  * we also match on the reply, duh
2623  */
2624 static int AppLayerProtoDetectTest11(void)
2625 {
2628 
2629  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2630  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2631  AppProto pm_results[g_alproto_max];
2632  memset(pm_results, 0, sizeof(pm_results));
2633  Flow f;
2634  memset(&f, 0x00, sizeof(f));
2635  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2636 
2638  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2640  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2642  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2644  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2646  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2648  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2650  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2652  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2653 
2655  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2656  * it sets internal structures which depends on the above function. */
2659 
2660  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2661  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2662  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2663  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2664 
2673 
2674  bool rdir = false;
2675  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2676  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2677  pm_results, &rdir);
2678  FAIL_IF(cnt != 1);
2679  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2680 
2681  memset(pm_results, 0, sizeof(pm_results));
2682  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2683  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2684  pm_results, &rdir);
2685  FAIL_IF(cnt != 1);
2686  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2687 
2691  PASS;
2692 }
2693 
2694 /**
2695  * \test AlpProtoSignature test
2696  */
2697 static int AppLayerProtoDetectTest12(void)
2698 {
2701 
2702  int r = 0;
2703 
2705  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2706  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2707  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2708  {
2709  printf("failure 1\n");
2710  goto end;
2711  }
2712 
2714  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2715  printf("failure 2\n");
2716  goto end;
2717  }
2718  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2719  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2720  {
2721  printf("failure 3\n");
2722  goto end;
2723  }
2724  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2725  printf("failure 4\n");
2726  goto end;
2727  }
2728  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2729  printf("failure 5\n");
2730  goto end;
2731  }
2732  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2733  printf("failure 6\n");
2734  goto end;
2735  }
2736 
2737  r = 1;
2738 
2739  end:
2742  return r;
2743 }
2744 
2745 /**
2746  * \test What about if we add some sigs only for udp but call for tcp?
2747  * It should not detect any proto
2748  */
2749 static int AppLayerProtoDetectTest13(void)
2750 {
2753 
2754  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2755  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2756  AppProto pm_results[g_alproto_max];
2757 
2758  Flow f;
2759  memset(&f, 0x00, sizeof(f));
2760  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2761 
2763  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2765  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2767  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2769  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2771  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2773  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2775  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2777  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2778 
2780  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2781  * it sets internal structures which depends on the above function. */
2783 
2784  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2785  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2786 
2795 
2796  memset(pm_results, 0, sizeof(pm_results));
2797  bool rdir = false;
2798  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2799  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2800  pm_results, &rdir);
2801  FAIL_IF(cnt != 0);
2802 
2803  memset(pm_results, 0, sizeof(pm_results));
2804  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2805  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2806  pm_results, &rdir);
2807  FAIL_IF(cnt != 0);
2808 
2812  PASS;
2813 }
2814 
2815 /**
2816  * \test What about if we add some sigs only for udp calling it for UDP?
2817  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2818  * to ensure that TCP/UDP differences work correctly.
2819  */
2820 static int AppLayerProtoDetectTest14(void)
2821 {
2824 
2825  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2826  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2827  AppProto pm_results[g_alproto_max];
2828  uint32_t cnt;
2829  Flow f;
2830  memset(&f, 0x00, sizeof(f));
2831  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2832 
2834  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2836  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2838  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2840  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2842  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2844  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2846  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2848  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2849 
2851  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2852  * it sets internal structures which depends on the above function. */
2855 
2856  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2857  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2858 
2867 
2868  memset(pm_results, 0, sizeof(pm_results));
2869  bool rdir = false;
2870  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2871  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2872  pm_results, &rdir);
2873  FAIL_IF(cnt != 1);
2874  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2875 
2876  memset(pm_results, 0, sizeof(pm_results));
2877  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2878  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2879  pm_results, &rdir);
2880  FAIL_IF(cnt != 1);
2881  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2882 
2886  PASS;
2887 }
2888 
2890  const char *alproto_name;
2892  uint16_t port;
2893  uint32_t min_depth;
2894  uint32_t max_depth;
2896 
2898  uint16_t port;
2899  uint16_t dp_max_depth;
2900  uint16_t sp_max_depth;
2901 
2907 
2908 
2910  uint8_t ipproto;
2911 
2915 
2916 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2918  int no_of_ip_proto)
2919 {
2920  int result = 0;
2921  int i = -1, j = -1 , k = -1;
2922 #ifdef DEBUG
2923  int dir = 0;
2924 #endif
2925  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2926  if (pp->ipproto != ip_proto[i].ipproto)
2927  goto end;
2928 
2930  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2931  if (pp_port->port != ip_proto[i].port[k].port)
2932  goto end;
2933  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2934  goto end;
2935  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2936  goto end;
2937 
2938  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2939 #ifdef DEBUG
2940  dir = 0;
2941 #endif
2942  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2943  j++, pp_element = pp_element->next) {
2944 
2945  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2946  goto end;
2947  }
2948  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2949  goto end;
2950  }
2951  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2952  goto end;
2953  }
2954  } /* for */
2955  if (pp_element != NULL)
2956  goto end;
2957 
2958  pp_element = pp_port->sp;
2959 #ifdef DEBUG
2960  dir = 1;
2961 #endif
2962  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2963  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2964  goto end;
2965  }
2966  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2967  goto end;
2968  }
2969  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2970  goto end;
2971  }
2972  } /* for */
2973  if (pp_element != NULL)
2974  goto end;
2975  }
2976  if (pp_port != NULL)
2977  goto end;
2978  }
2979  if (pp != NULL)
2980  goto end;
2981 
2982  result = 1;
2983  end:
2984 #ifdef DEBUG
2985  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2986 #endif
2987  return result;
2988 }
2989 
2990 static uint16_t ProbingParserDummyForTesting(
2991  const Flow *f, uint8_t direction, const uint8_t *input, uint32_t input_len, uint8_t *rdir)
2992 {
2993  return 0;
2994 }
2995 
2996 static int AppLayerProtoDetectTest15(void)
2997 {
3000 
3001  int result = 0;
3002 
3003  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
3004  ProbingParserDummyForTesting, NULL);
3005  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_SMB, 5, 6, STREAM_TOSERVER,
3006  ProbingParserDummyForTesting, NULL);
3007  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_FTP, 7, 10, STREAM_TOSERVER,
3008  ProbingParserDummyForTesting, NULL);
3009 
3010  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_DCERPC, 9, 10, STREAM_TOSERVER,
3011  ProbingParserDummyForTesting, NULL);
3012  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_FTP, 7, 15, STREAM_TOSERVER,
3013  ProbingParserDummyForTesting, NULL);
3014  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_SMTP, 12, 0, STREAM_TOSERVER,
3015  ProbingParserDummyForTesting, NULL);
3016  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_TLS, 12, 18, STREAM_TOSERVER,
3017  ProbingParserDummyForTesting, NULL);
3018 
3019  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_DCERPC, 9, 10, STREAM_TOSERVER,
3020  ProbingParserDummyForTesting, NULL);
3021  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_FTP, 7, 15, STREAM_TOSERVER,
3022  ProbingParserDummyForTesting, NULL);
3023  result = 1;
3024 
3025  SCAppLayerProtoDetectPPRegister(IPPROTO_UDP, "85", ALPROTO_IMAP, 12, 23, STREAM_TOSERVER,
3026  ProbingParserDummyForTesting, NULL);
3027 
3028  /* toclient */
3029  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_JABBER, 12, 23, STREAM_TOCLIENT,
3030  ProbingParserDummyForTesting, NULL);
3031  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_IRC, 12, 14, STREAM_TOCLIENT,
3032  ProbingParserDummyForTesting, NULL);
3033 
3034  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_DCERPC, 9, 10, STREAM_TOCLIENT,
3035  ProbingParserDummyForTesting, NULL);
3036  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_FTP, 7, 15, STREAM_TOCLIENT,
3037  ProbingParserDummyForTesting, NULL);
3038  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_TLS, 12, 18, STREAM_TOCLIENT,
3039  ProbingParserDummyForTesting, NULL);
3040  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3041  ProbingParserDummyForTesting, NULL);
3042  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_DCERPC, 9, 10, STREAM_TOCLIENT,
3043  ProbingParserDummyForTesting, NULL);
3044  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "90", ALPROTO_FTP, 7, 15, STREAM_TOCLIENT,
3045  ProbingParserDummyForTesting, NULL);
3046  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_SMB, 5, 6, STREAM_TOCLIENT,
3047  ProbingParserDummyForTesting, NULL);
3048  SCAppLayerProtoDetectPPRegister(IPPROTO_UDP, "85", ALPROTO_IMAP, 12, 23, STREAM_TOCLIENT,
3049  ProbingParserDummyForTesting, NULL);
3050  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_SMTP, 12, 17, STREAM_TOCLIENT,
3051  ProbingParserDummyForTesting, NULL);
3052  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_FTP, 7, 10, STREAM_TOCLIENT,
3053  ProbingParserDummyForTesting, NULL);
3054 
3055  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3056  { "http", ALPROTO_HTTP1, 80, 5, 8 },
3057  { "smb", ALPROTO_SMB, 80, 5, 6 },
3058  { "ftp", ALPROTO_FTP, 80, 7, 10 },
3059  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3060  { "tls", ALPROTO_TLS, 0, 12, 18 },
3061  { "irc", ALPROTO_IRC, 0, 12, 25 },
3062  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3063  };
3064  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80, 5, 8 },
3065  { "smb", ALPROTO_SMB, 80, 5, 6 }, { "ftp", ALPROTO_FTP, 80, 7, 10 },
3066  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3067  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3068 
3069  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3070  { "dcerpc", ALPROTO_DCERPC, 81, 9, 10 },
3071  { "ftp", ALPROTO_FTP, 81, 7, 15 },
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_81[] = { { "ftp", ALPROTO_FTP, 81, 7, 15 },
3078  { "dcerpc", ALPROTO_DCERPC, 81, 9, 10 }, { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3079  { "irc", ALPROTO_IRC, 0, 12, 14 }, { "tls", ALPROTO_TLS, 0, 12, 18 },
3080  { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3081 
3082  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3083  { "dcerpc", ALPROTO_DCERPC, 85, 9, 10 },
3084  { "ftp", ALPROTO_FTP, 85, 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_85[] = { { "dcerpc", ALPROTO_DCERPC, 85, 9,
3091  10 },
3092  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3093  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3094 
3095  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3096  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3097  { "tls", ALPROTO_TLS, 0, 12, 18 },
3098  { "irc", ALPROTO_IRC, 0, 12, 25 },
3099  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3100  };
3101  AppLayerProtoDetectPPTestDataElement element_tc_90[] = { { "ftp", ALPROTO_FTP, 90, 7, 15 },
3102  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3103  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3104 
3105  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3106  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3107  { "tls", ALPROTO_TLS, 0, 12, 18 },
3108  { "irc", ALPROTO_IRC, 0, 12, 25 },
3109  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3110  };
3111  AppLayerProtoDetectPPTestDataElement element_tc_0[] = { { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3112  { "irc", ALPROTO_IRC, 0, 12, 14 }, { "tls", ALPROTO_TLS, 0, 12, 18 },
3113  { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3114 
3115  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3116  { "imap", ALPROTO_IMAP, 85, 12, 23 },
3117  };
3118  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3119  { "imap", ALPROTO_IMAP, 85, 12, 23 },
3120  };
3121 
3122  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3123  {
3124  80,
3125  23,
3126  23,
3127  element_ts_80,
3128  element_tc_80,
3129  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3130  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3131  },
3132  {
3133  81,
3134  23,
3135  23,
3136  element_ts_81,
3137  element_tc_81,
3138  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3139  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3140  },
3141  { 85, 23, 23, element_ts_85, element_tc_85,
3142  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3143  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3144  { 90, 23, 23, element_ts_90, element_tc_90,
3145  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3146  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3147  { 0, 23, 23, element_ts_0, element_tc_0,
3148  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3149  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3150  };
3151 
3152  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3153  {
3154  85,
3155  23,
3156  23,
3157  element_ts_85_udp,
3158  element_tc_85_udp,
3159  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3160  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3161  },
3162  };
3163 
3165  { IPPROTO_TCP,
3166  ports_tcp,
3167  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3168  },
3169  { IPPROTO_UDP,
3170  ports_udp,
3171  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3172  },
3173  };
3174 
3175 
3176  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3177  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3178  goto end;
3179  }
3180  result = 1;
3181 
3182  end:
3185  return result;
3186 }
3187 
3188 
3189 /** \test test if the engine detect the proto and match with it */
3190 static int AppLayerProtoDetectTest16(void)
3191 {
3192  int result = 0;
3193  Flow *f = NULL;
3194  HtpState *http_state = NULL;
3195  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3196  "User-Agent: Mozilla/1.0\r\n"
3197  "Cookie: hellocatch\r\n\r\n";
3198  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3199  TcpSession ssn;
3200  Packet *p = NULL;
3201  Signature *s = NULL;
3202  ThreadVars tv;
3203  DetectEngineThreadCtx *det_ctx = NULL;
3204  DetectEngineCtx *de_ctx = NULL;
3206 
3207  memset(&tv, 0, sizeof(ThreadVars));
3209  memset(&ssn, 0, sizeof(TcpSession));
3210 
3211  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3212  if (p == NULL) {
3213  printf("packet setup failed: ");
3214  goto end;
3215  }
3216 
3217  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3218  if (f == NULL) {
3219  printf("flow setup failed: ");
3220  goto end;
3221  }
3222  f->protoctx = &ssn;
3223  f->proto = IPPROTO_TCP;
3224  p->flow = f;
3225 
3229 
3230  f->alproto = ALPROTO_HTTP1;
3231 
3232  StreamTcpInitConfig(true);
3233 
3235  if (de_ctx == NULL) {
3236  goto end;
3237  }
3238  de_ctx->flags |= DE_QUIET;
3239 
3240  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3241  "(msg:\"Test content option\"; "
3242  "sid:1;)");
3243  if (s == NULL) {
3244  goto end;
3245  }
3246 
3248  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3249 
3250  int r = AppLayerParserParse(
3251  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3252  if (r != 0) {
3253  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3254  goto end;
3255  }
3256 
3257  http_state = f->alstate;
3258  if (http_state == NULL) {
3259  printf("no http state: ");
3260  goto end;
3261  }
3262 
3263  /* do detect */
3264  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3265 
3266  if (!PacketAlertCheck(p, 1)) {
3267  printf("sig 1 didn't alert, but it should: ");
3268  goto end;
3269  }
3270  result = 1;
3271  end:
3272  UTHFreePackets(&p, 1);
3273  UTHFreeFlow(f);
3274  if (alp_tctx != NULL)
3276  if (det_ctx != NULL)
3277  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3278  if (de_ctx != NULL)
3280  StreamTcpFreeConfig(true);
3282  return result;
3283 }
3284 
3285 /** \test test if the engine detect the proto on a non standar port
3286  * and match with it */
3287 static int AppLayerProtoDetectTest17(void)
3288 {
3289  int result = 0;
3290  Flow *f = NULL;
3291  HtpState *http_state = NULL;
3292  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3293  "User-Agent: Mozilla/1.0\r\n"
3294  "Cookie: hellocatch\r\n\r\n";
3295  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3296  TcpSession ssn;
3297  Packet *p = NULL;
3298  Signature *s = NULL;
3299  ThreadVars tv;
3300  DetectEngineThreadCtx *det_ctx = NULL;
3301  DetectEngineCtx *de_ctx = NULL;
3303 
3304  memset(&tv, 0, sizeof(ThreadVars));
3306  memset(&ssn, 0, sizeof(TcpSession));
3307 
3308  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3309 
3310  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3311  if (f == NULL)
3312  goto end;
3313  f->protoctx = &ssn;
3314  f->proto = IPPROTO_TCP;
3315  p->flow = f;
3319  f->alproto = ALPROTO_HTTP1;
3320 
3321  StreamTcpInitConfig(true);
3322 
3324  if (de_ctx == NULL) {
3325  goto end;
3326  }
3327  de_ctx->flags |= DE_QUIET;
3328 
3329  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3330  "(msg:\"http over non standar port\"; "
3331  "sid:1;)");
3332  if (s == NULL) {
3333  goto end;
3334  }
3335 
3337  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3338 
3339  int r = AppLayerParserParse(
3340  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3341  if (r != 0) {
3342  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3343  goto end;
3344  }
3345 
3346  http_state = f->alstate;
3347  if (http_state == NULL) {
3348  printf("no http state: ");
3349  goto end;
3350  }
3351 
3352  /* do detect */
3353  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3354 
3355  if (!PacketAlertCheck(p, 1)) {
3356  printf("sig 1 didn't alert, but it should: ");
3357  goto end;
3358  }
3359 
3360  result = 1;
3361 
3362  end:
3363  UTHFreePackets(&p, 1);
3364  UTHFreeFlow(f);
3365  if (alp_tctx != NULL)
3367  if (det_ctx != NULL)
3368  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3369  if (de_ctx != NULL)
3371  StreamTcpFreeConfig(true);
3373  return result;
3374 }
3375 
3376 /** \test test if the engine detect the proto and doesn't match
3377  * because the sig expects another proto (ex ftp)*/
3378 static int AppLayerProtoDetectTest18(void)
3379 {
3380  int result = 0;
3381  Flow *f = NULL;
3382  HtpState *http_state = NULL;
3383  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3384  "User-Agent: Mozilla/1.0\r\n"
3385  "Cookie: hellocatch\r\n\r\n";
3386  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3387  TcpSession ssn;
3388  Packet *p = NULL;
3389  Signature *s = NULL;
3390  ThreadVars tv;
3391  DetectEngineThreadCtx *det_ctx = NULL;
3392  DetectEngineCtx *de_ctx = NULL;
3394 
3395  memset(&tv, 0, sizeof(ThreadVars));
3397  memset(&ssn, 0, sizeof(TcpSession));
3398 
3399  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3400 
3401  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3402  if (f == NULL)
3403  goto end;
3404  f->protoctx = &ssn;
3405  f->proto = IPPROTO_TCP;
3406  p->flow = f;
3410  f->alproto = ALPROTO_HTTP1;
3411 
3412  StreamTcpInitConfig(true);
3413 
3415  if (de_ctx == NULL) {
3416  goto end;
3417  }
3418  de_ctx->flags |= DE_QUIET;
3419 
3420  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3421  "(msg:\"Test content option\"; "
3422  "sid:1;)");
3423  if (s == NULL) {
3424  goto end;
3425  }
3426 
3428  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3429 
3430  int r = AppLayerParserParse(
3431  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3432  if (r != 0) {
3433  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3434  goto end;
3435  }
3436 
3437  http_state = f->alstate;
3438  if (http_state == NULL) {
3439  printf("no http state: ");
3440  goto end;
3441  }
3442 
3443  /* do detect */
3444  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3445 
3446  if (PacketAlertCheck(p, 1)) {
3447  printf("sig 1 alerted, but it should not (it's not ftp): ");
3448  goto end;
3449  }
3450 
3451  result = 1;
3452  end:
3453  UTHFreePackets(&p, 1);
3454  UTHFreeFlow(f);
3455  if (alp_tctx != NULL)
3457  if (det_ctx != NULL)
3458  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3459  if (de_ctx != NULL)
3461  StreamTcpFreeConfig(true);
3463  return result;
3464 }
3465 
3466 /** \test test if the engine detect the proto and doesn't match
3467  * because the packet has another proto (ex ftp) */
3468 static int AppLayerProtoDetectTest19(void)
3469 {
3470  int result = 0;
3471  Flow *f = NULL;
3472  uint8_t http_buf1[] = "MPUT one\r\n";
3473  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3474  TcpSession ssn;
3475  Packet *p = NULL;
3476  Signature *s = NULL;
3477  ThreadVars tv;
3478  DetectEngineThreadCtx *det_ctx = NULL;
3479  DetectEngineCtx *de_ctx = NULL;
3481 
3482  memset(&tv, 0, sizeof(ThreadVars));
3484  memset(&ssn, 0, sizeof(TcpSession));
3485 
3486  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3487 
3488  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3489  if (f == NULL)
3490  goto end;
3491  f->protoctx = &ssn;
3492  f->proto = IPPROTO_TCP;
3493  p->flow = f;
3497  f->alproto = ALPROTO_FTP;
3498 
3499  StreamTcpInitConfig(true);
3500 
3502  if (de_ctx == NULL) {
3503  goto end;
3504  }
3505  de_ctx->flags |= DE_QUIET;
3506 
3507  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3508  "(msg:\"http over non standar port\"; "
3509  "sid:1;)");
3510  if (s == NULL) {
3511  goto end;
3512  }
3513 
3515  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3516 
3517  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3518  STREAM_TOSERVER, http_buf1, http_buf1_len);
3519  if (r != 0) {
3520  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3521  goto end;
3522  }
3523 
3524  /* do detect */
3525  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3526 
3527  if (PacketAlertCheck(p, 1)) {
3528  printf("sig 1 alerted, but it should not (it's ftp): ");
3529  goto end;
3530  }
3531 
3532  result = 1;
3533 
3534  end:
3535  UTHFreePackets(&p, 1);
3536  UTHFreeFlow(f);
3537  if (alp_tctx != NULL)
3539  if (det_ctx != NULL)
3540  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3541  if (de_ctx != NULL)
3543  StreamTcpFreeConfig(true);
3545  return result;
3546 }
3547 
3549 {
3550  SCEnter();
3551 
3552  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3553  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3554  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3555  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3556  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3557  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3558  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3559  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3560  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3561  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3562  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3563  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3564  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3565  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3566  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3567  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3568  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3569  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3570  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3571 
3572  SCReturn;
3573 }
3574 
3575 #endif /* UNITTESTS */
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:195
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2897
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:2185
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:1268
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:547
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:2177
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2890
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:2066
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:2893
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:2891
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2420
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:532
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:2909
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:1982
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:1138
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:3414
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:2902
alpd_tctx
AppLayerProtoDetectThreadCtx * alpd_tctx
Definition: fuzz_applayerprotodetectgetproto.c:23
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:69
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3104
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:2913
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:2903
Packet_
Definition: decode.h:501
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:2158
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2905
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:2899
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:2898
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:274
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:2207
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:827
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:549
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:1297
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:2910
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:3651
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:2128
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:3548
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:2894
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1987
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2086
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:2904
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:2040
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:2892
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:2900
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:1264
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2912
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2111
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:2889