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  if (!FlowChangeProto(f)) {
1888  // may happen when changing protocol from http1 to http2, then doh2
1889  // We need to keep the original alproto, as HTTP1 state was not freed yet
1890  f->alproto_orig = f->alproto;
1891  } else if (f->alproto == f->alproto_expect) {
1892  // First change went as expected
1893  f->alproto_expect = new_proto;
1894  }
1895  f->alproto = new_proto;
1896  f->alproto_ts = f->alproto;
1897  f->alproto_tc = f->alproto;
1898  }
1899 }
1900 
1902 {
1903  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1904  FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1905  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1906  FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1907  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1908  FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1911  // Does not free the structures for the parser
1912  // keeps f->alstate for new state creation
1913  f->alparser = NULL;
1914  f->alproto = ALPROTO_UNKNOWN;
1917 }
1918 
1920  const char *ipproto, const char *alproto, bool default_enabled)
1921 {
1922  SCEnter();
1923 
1924  BUG_ON(ipproto == NULL || alproto == NULL);
1925 
1926  char param[100];
1927  SCConfNode *g_proto, *i_proto;
1928  int r;
1929  bool g_enabled = false;
1930  bool i_enabled = false;
1931 
1932  if (RunmodeIsUnittests())
1933  SCReturnInt(1);
1934 
1935 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1936  // so that fuzzig takes place for DNP3 and such
1937  default_enabled = true;
1938 #endif
1939 
1940  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.", alproto, ".", ipproto,
1941  ".enabled");
1942  if (r < 0) {
1943  FatalError("snprintf failure.");
1944  } else if (r > (int)sizeof(param)) {
1945  FatalError("buffer not big enough to write param.");
1946  }
1947  SCLogDebug("Looking for %s", param);
1948 
1949  i_proto = SCConfGetNode(param);
1950  if (i_proto && i_proto->val) {
1951  if (SCConfValIsTrue(i_proto->val)) {
1952  i_enabled = true;
1953  } else if (SCConfValIsFalse(i_proto->val)) {
1954  i_enabled = false;
1955  } else if (strcasecmp(i_proto->val, "detection-only") == 0) {
1956  i_enabled = true;
1957  } else {
1958  FatalError("Invalid value found for %s.", param);
1959  }
1960  }
1961 
1962  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.", alproto, ".enabled");
1963  if (r < 0) {
1964  FatalError("snprintf failure.");
1965  } else if (r > (int)sizeof(param)) {
1966  FatalError("buffer not big enough to write param.");
1967  }
1968 
1969  SCLogDebug("Looking for %s", param);
1970  g_proto = SCConfGetNode(param);
1971  if (g_proto && g_proto->val) {
1972  if (SCConfValIsTrue(g_proto->val)) {
1973  g_enabled = true;
1974  } else if (SCConfValIsFalse(g_proto->val)) {
1975  g_enabled = false;
1976  } else if (strcasecmp(g_proto->val, "detection-only") == 0) {
1977  g_enabled = true;
1978  } else {
1979  FatalError("Invalid value found for %s", param);
1980  }
1981  }
1982 
1983  if ((i_proto && g_proto) && (i_enabled ^ g_enabled)) {
1984  SCLogWarning("Inconsistent global (%s) and respective ipproto (%s) settings found for "
1985  "alproto %s and ipproto %s",
1986  g_enabled ? "TRUE" : "FALSE", i_enabled ? "TRUE" : "FALSE", alproto, ipproto);
1987  }
1988 
1989  if (i_proto) {
1990  SCReturnInt(i_enabled);
1991  }
1992  if (g_proto) {
1993  SCReturnInt(g_enabled);
1994  }
1995  if (!default_enabled) {
1996  SCReturnInt(0);
1997  }
1998 
1999  SCReturnInt(1);
2000 }
2001 
2002 int SCAppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
2003 {
2004  return SCAppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
2005 }
2006 
2008 {
2009  SCEnter();
2010 
2012  MpmCtx *mpm_ctx;
2013  MpmThreadCtx *mpm_tctx;
2014  int i, j;
2015  PatIntId max_pat_id = 0;
2016 
2017  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2018  for (j = 0; j < 2; j++) {
2019  if (max_pat_id == 0) {
2020  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2021 
2022  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
2023  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
2024  {
2025  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2026  }
2027  }
2028  }
2029 
2030  alpd_tctx = SCCalloc(1, sizeof(*alpd_tctx));
2031  if (alpd_tctx == NULL)
2032  goto error;
2033 
2034  /* Get the max pat id for all the mpm ctxs. */
2035  if (PmqSetup(&alpd_tctx->pmq) < 0)
2036  goto error;
2037 
2038  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2039  for (j = 0; j < 2; j++) {
2040  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
2041  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
2042  MpmInitThreadCtx(mpm_tctx, mpm_ctx, mpm_ctx->mpm_type);
2043  }
2044  }
2045 
2047  if (alpd_tctx->spm_thread_ctx == NULL) {
2048  goto error;
2049  }
2050 
2051  goto end;
2052  error:
2053  if (alpd_tctx != NULL)
2055  alpd_tctx = NULL;
2056  end:
2057  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2058 }
2059 
2061 {
2062  SCEnter();
2063 
2064  MpmCtx *mpm_ctx;
2065  MpmThreadCtx *mpm_tctx;
2066  int ipproto_map, dir;
2067 
2068  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2069  for (dir = 0; dir < 2; dir++) {
2070  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2071  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2072  MpmDestroyThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2073  }
2074  }
2075  PmqFree(&alpd_tctx->pmq);
2076  if (alpd_tctx->spm_thread_ctx != NULL) {
2078  }
2079  SCFree(alpd_tctx);
2080 
2081  SCReturn;
2082 }
2083 
2084 /***** Utility *****/
2085 
2086 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2087 {
2088  SCEnter();
2089 
2090  // Custom case for only signature-only protocol so far
2091  if (alproto == ALPROTO_HTTP) {
2094  } else if (alproto == ALPROTO_DOH2) {
2095  // DOH2 is not detected, just HTTP2
2097  } else {
2098  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2099  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2100  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2101  }
2102 
2103  SCReturn;
2104 }
2105 
2107 {
2108  SCEnter();
2109 
2110  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2111  while (cur_alias != NULL) {
2112  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2113  alproto_name = cur_alias->proto_name;
2114  }
2115 
2116  cur_alias = cur_alias->next;
2117  }
2118 
2119  AppProto a;
2120  AppProto b = StringToAppProto(alproto_name);
2121  for (a = 0; a < g_alproto_max; a++) {
2122  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2123  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2124  SCReturnCT(b, "AppProto");
2125  }
2126  }
2127 
2128  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2129 }
2130 
2132 {
2133  // Special case for http (any version) :
2134  // returns "http" if both versions are enabled
2135  // and returns "http1" or "http2" if only one version is enabled
2136  if (alproto == ALPROTO_HTTP) {
2137  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2138  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2139  return "http";
2140  } // else
2141  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2142  } // else
2143  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2144  }
2145  return alpd_ctx.alproto_names[alproto];
2146 }
2147 
2149 {
2150  SCEnter();
2151 
2152  memset(alprotos, 0, g_alproto_max * sizeof(AppProto));
2153 
2154  int alproto;
2155 
2156  for (alproto = 0; alproto != g_alproto_max; alproto++) {
2157  if (alpd_ctx.alproto_names[alproto] != NULL)
2158  alprotos[alproto] = 1;
2159  }
2160 
2161  SCReturn;
2162 }
2163 
2164 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2165  uint8_t *ipprotos)
2166 {
2167  if (alproto >= alpd_ctx.expectation_proto_len) {
2168  return;
2169  }
2170  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_TCP) {
2171  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2172  }
2173  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_UDP) {
2174  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2175  }
2176 }
2177 
2179 {
2180  if (alpd_ctx.expectation_proto[alproto]) {
2181  if (proto != alpd_ctx.expectation_proto[alproto]) {
2182  SCLogError("Expectation on 2 IP protocols are not supported");
2183  }
2184  }
2185  alpd_ctx.expectation_proto[alproto] = proto;
2186 }
2187 
2188 /***** Unittests *****/
2189 
2190 #ifdef UNITTESTS
2191 
2192 #include "app-layer-htp.h"
2193 #include "detect-engine-alert.h"
2194 
2195 static AppLayerProtoDetectCtx alpd_ctx_ut;
2196 
2198 {
2199  SCEnter();
2200  alpd_ctx_ut = alpd_ctx;
2201  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2202  SCReturn;
2203 }
2204 
2206 {
2207  SCEnter();
2208  alpd_ctx = alpd_ctx_ut;
2209  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2210  SCReturn;
2211 }
2212 
2213 static int AppLayerProtoDetectTest01(void)
2214 {
2217 
2218  const char *buf = "HTTP";
2220  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2221  buf = "GET";
2223  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2224 
2226  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2227  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2228 
2231  PASS;
2232 }
2233 
2234 static int AppLayerProtoDetectTest02(void)
2235 {
2238 
2239  const char *buf = "HTTP";
2241  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2242  buf = "ftp";
2243  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2244 
2246  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2247  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2248 
2249  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2250  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2251 
2254 
2257  PASS;
2258 }
2259 
2260 static int AppLayerProtoDetectTest03(void)
2261 {
2264 
2265  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2266  AppProto pm_results[g_alproto_max];
2267  memset(pm_results, 0, sizeof(pm_results));
2268  Flow f;
2269  memset(&f, 0x00, sizeof(f));
2270  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2271 
2272 
2273  const char *buf = "HTTP";
2275  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2276  buf = "220 ";
2277  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2278 
2280  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2281  * it sets internal structures which depends on the above function. */
2284 
2285  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2286  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2287  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2288  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2291 
2292  bool rflow = false;
2293  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2294  &f, l7data, sizeof(l7data),
2295  STREAM_TOCLIENT,
2296  pm_results, &rflow);
2297  FAIL_IF(cnt != 1);
2298  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2299 
2303  PASS;
2304 }
2305 
2306 static int AppLayerProtoDetectTest04(void)
2307 {
2310 
2311  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2312  Flow f;
2313  memset(&f, 0x00, sizeof(f));
2314  AppProto pm_results[g_alproto_max];
2315  memset(pm_results, 0, sizeof(pm_results));
2316  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2317 
2318  const char *buf = "200 ";
2320  IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2321 
2323  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2324  * it sets internal structures which depends on the above function. */
2327 
2328  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2329  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2330  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2331  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2333 
2334  bool rdir = false;
2335  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2336  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2337  pm_results, &rdir);
2338  FAIL_IF(cnt != 1);
2339  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2340 
2344  PASS;
2345 }
2346 
2347 static int AppLayerProtoDetectTest05(void)
2348 {
2351 
2352  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2353  AppProto pm_results[g_alproto_max];
2354  memset(pm_results, 0, sizeof(pm_results));
2355  Flow f;
2356  memset(&f, 0x00, sizeof(f));
2357  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2358 
2359  const char *buf = "HTTP";
2361  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2362  buf = "220 ";
2363  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2364 
2366  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2367  * it sets internal structures which depends on the above function. */
2370 
2371  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2372  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2373  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2374  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2377 
2378  bool rdir = false;
2379  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2380  &f, l7data, sizeof(l7data),
2381  STREAM_TOCLIENT,
2382  pm_results, &rdir);
2383  FAIL_IF(cnt != 1);
2384  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2385 
2389  PASS;
2390 }
2391 
2392 static int AppLayerProtoDetectTest06(void)
2393 {
2396 
2397  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2398  AppProto pm_results[g_alproto_max];
2399  memset(pm_results, 0, sizeof(pm_results));
2400  Flow f;
2401  memset(&f, 0x00, sizeof(f));
2402  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2403 
2404  const char *buf = "HTTP";
2406  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2407  buf = "220 ";
2408  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2409 
2411  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2412  * it sets internal structures which depends on the above function. */
2415 
2416  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2417  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2418  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2419  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2422 
2423  bool rdir = false;
2424  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2425  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2426  pm_results, &rdir);
2427  FAIL_IF(cnt != 1);
2428  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2429 
2433  PASS;
2434 }
2435 
2436 static int AppLayerProtoDetectTest07(void)
2437 {
2440 
2441  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2442  Flow f;
2443  memset(&f, 0x00, sizeof(f));
2444  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2445  AppProto pm_results[g_alproto_max];
2446  memset(pm_results, 0, sizeof(pm_results));
2447 
2448  const char *buf = "HTTP";
2450  IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2451 
2453  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2454  * it sets internal structures which depends on the above function. */
2456 
2457  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2458  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2459  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2460  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2462 
2463  bool rdir = false;
2464  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2465  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2466  pm_results, &rdir);
2467  FAIL_IF(cnt != 0);
2468 
2472  PASS;
2473 }
2474 
2475 static int AppLayerProtoDetectTest08(void)
2476 {
2479 
2480  uint8_t l7data[] = {
2481  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2482  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2483  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2484  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2485  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2486  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2487  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2488  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2489  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2490  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2491  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2492  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2493  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2494  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2495  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2496  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2497  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2498  0x00
2499  };
2500  AppProto pm_results[g_alproto_max];
2501  memset(pm_results, 0, sizeof(pm_results));
2502  Flow f;
2503  memset(&f, 0x00, sizeof(f));
2504  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2505 
2506  const char *buf = "|ff|SMB";
2507  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2508 
2510  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2511  * it sets internal structures which depends on the above function. */
2514 
2515  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2516  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2517  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2518  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2520 
2521  bool rdir = false;
2522  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2523  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2524  pm_results, &rdir);
2525  FAIL_IF(cnt != 1);
2526  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2527 
2531  PASS;
2532 }
2533 
2534 static int AppLayerProtoDetectTest09(void)
2535 {
2538 
2539  uint8_t l7data[] = {
2540  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2541  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2542  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2543  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2544  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2545  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2546  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2547  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2548  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2549  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2550  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2551  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2552  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2553  0x00, 0x02, 0x02
2554  };
2555  AppProto pm_results[g_alproto_max];
2556  memset(pm_results, 0, sizeof(pm_results));
2557  Flow f;
2558  memset(&f, 0x00, sizeof(f));
2559  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2560 
2561  const char *buf = "|fe|SMB";
2562  SCAppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2563 
2565  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2566  * it sets internal structures which depends on the above function. */
2569 
2570  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2571  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2572  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2573  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2575 
2576  bool rdir = false;
2577  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2578  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2579  pm_results, &rdir);
2580  FAIL_IF(cnt != 1);
2581  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2582 
2586  PASS;
2587 }
2588 
2589 static int AppLayerProtoDetectTest10(void)
2590 {
2593 
2594  uint8_t l7data[] = {
2595  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2596  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2597  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2598  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2599  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2600  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2601  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2602  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2603  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2604  };
2605  AppProto pm_results[g_alproto_max];
2606  memset(pm_results, 0, sizeof(pm_results));
2607  Flow f;
2608  memset(&f, 0x00, sizeof(f));
2609  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2610 
2611  const char *buf = "|05 00|";
2613  IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2614 
2616  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2617  * it sets internal structures which depends on the above function. */
2620 
2621  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2622  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2623  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2624  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2626 
2627  bool rdir = false;
2628  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2629  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2630  pm_results, &rdir);
2631  FAIL_IF(cnt != 1);
2632  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2633 
2637  PASS;
2638 }
2639 
2640 /**
2641  * \test Why we still get http for connect... obviously because
2642  * we also match on the reply, duh
2643  */
2644 static int AppLayerProtoDetectTest11(void)
2645 {
2648 
2649  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2650  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2651  AppProto pm_results[g_alproto_max];
2652  memset(pm_results, 0, sizeof(pm_results));
2653  Flow f;
2654  memset(&f, 0x00, sizeof(f));
2655  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2656 
2658  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2660  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2662  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2664  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2666  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2668  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2670  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2672  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2673 
2675  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2676  * it sets internal structures which depends on the above function. */
2679 
2680  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2681  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2682  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2683  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2684 
2693 
2694  bool rdir = false;
2695  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2696  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2697  pm_results, &rdir);
2698  FAIL_IF(cnt != 1);
2699  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2700 
2701  memset(pm_results, 0, sizeof(pm_results));
2702  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2703  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2704  pm_results, &rdir);
2705  FAIL_IF(cnt != 1);
2706  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2707 
2711  PASS;
2712 }
2713 
2714 /**
2715  * \test AlpProtoSignature test
2716  */
2717 static int AppLayerProtoDetectTest12(void)
2718 {
2721 
2722  int r = 0;
2723 
2725  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2726  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2727  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2728  {
2729  printf("failure 1\n");
2730  goto end;
2731  }
2732 
2734  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2735  printf("failure 2\n");
2736  goto end;
2737  }
2738  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2739  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2740  {
2741  printf("failure 3\n");
2742  goto end;
2743  }
2744  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2745  printf("failure 4\n");
2746  goto end;
2747  }
2748  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2749  printf("failure 5\n");
2750  goto end;
2751  }
2752  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2753  printf("failure 6\n");
2754  goto end;
2755  }
2756 
2757  r = 1;
2758 
2759  end:
2762  return r;
2763 }
2764 
2765 /**
2766  * \test What about if we add some sigs only for udp but call for tcp?
2767  * It should not detect any proto
2768  */
2769 static int AppLayerProtoDetectTest13(void)
2770 {
2773 
2774  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2775  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2776  AppProto pm_results[g_alproto_max];
2777 
2778  Flow f;
2779  memset(&f, 0x00, sizeof(f));
2780  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2781 
2783  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2785  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2787  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2789  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2791  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2793  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2795  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2797  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2798 
2800  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2801  * it sets internal structures which depends on the above function. */
2803 
2804  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2805  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2806 
2815 
2816  memset(pm_results, 0, sizeof(pm_results));
2817  bool rdir = false;
2818  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2819  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2820  pm_results, &rdir);
2821  FAIL_IF(cnt != 0);
2822 
2823  memset(pm_results, 0, sizeof(pm_results));
2824  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2825  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2826  pm_results, &rdir);
2827  FAIL_IF(cnt != 0);
2828 
2832  PASS;
2833 }
2834 
2835 /**
2836  * \test What about if we add some sigs only for udp calling it for UDP?
2837  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2838  * to ensure that TCP/UDP differences work correctly.
2839  */
2840 static int AppLayerProtoDetectTest14(void)
2841 {
2844 
2845  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2846  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2847  AppProto pm_results[g_alproto_max];
2848  uint32_t cnt;
2849  Flow f;
2850  memset(&f, 0x00, sizeof(f));
2851  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2852 
2854  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2856  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2858  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2860  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2862  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2864  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2866  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2868  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2869 
2871  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2872  * it sets internal structures which depends on the above function. */
2875 
2876  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2877  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2878 
2887 
2888  memset(pm_results, 0, sizeof(pm_results));
2889  bool rdir = false;
2890  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2891  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2892  pm_results, &rdir);
2893  FAIL_IF(cnt != 1);
2894  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2895 
2896  memset(pm_results, 0, sizeof(pm_results));
2897  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2898  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2899  pm_results, &rdir);
2900  FAIL_IF(cnt != 1);
2901  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2902 
2906  PASS;
2907 }
2908 
2910  const char *alproto_name;
2912  uint16_t port;
2913  uint32_t min_depth;
2914  uint32_t max_depth;
2916 
2918  uint16_t port;
2919  uint16_t dp_max_depth;
2920  uint16_t sp_max_depth;
2921 
2927 
2928 
2930  uint8_t ipproto;
2931 
2935 
2936 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2938  int no_of_ip_proto)
2939 {
2940  int result = 0;
2941  int i = -1, j = -1 , k = -1;
2942 #ifdef DEBUG
2943  int dir = 0;
2944 #endif
2945  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2946  if (pp->ipproto != ip_proto[i].ipproto)
2947  goto end;
2948 
2950  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2951  if (pp_port->port != ip_proto[i].port[k].port)
2952  goto end;
2953  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2954  goto end;
2955  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2956  goto end;
2957 
2958  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2959 #ifdef DEBUG
2960  dir = 0;
2961 #endif
2962  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2963  j++, pp_element = pp_element->next) {
2964 
2965  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2966  goto end;
2967  }
2968  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2969  goto end;
2970  }
2971  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2972  goto end;
2973  }
2974  } /* for */
2975  if (pp_element != NULL)
2976  goto end;
2977 
2978  pp_element = pp_port->sp;
2979 #ifdef DEBUG
2980  dir = 1;
2981 #endif
2982  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2983  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2984  goto end;
2985  }
2986  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2987  goto end;
2988  }
2989  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2990  goto end;
2991  }
2992  } /* for */
2993  if (pp_element != NULL)
2994  goto end;
2995  }
2996  if (pp_port != NULL)
2997  goto end;
2998  }
2999  if (pp != NULL)
3000  goto end;
3001 
3002  result = 1;
3003  end:
3004 #ifdef DEBUG
3005  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
3006 #endif
3007  return result;
3008 }
3009 
3010 static uint16_t ProbingParserDummyForTesting(
3011  const Flow *f, uint8_t direction, const uint8_t *input, uint32_t input_len, uint8_t *rdir)
3012 {
3013  return 0;
3014 }
3015 
3016 static int AppLayerProtoDetectTest15(void)
3017 {
3020 
3021  int result = 0;
3022 
3023  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
3024  ProbingParserDummyForTesting, NULL);
3025  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_SMB, 5, 6, STREAM_TOSERVER,
3026  ProbingParserDummyForTesting, NULL);
3027  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_FTP, 7, 10, STREAM_TOSERVER,
3028  ProbingParserDummyForTesting, NULL);
3029 
3030  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_DCERPC, 9, 10, STREAM_TOSERVER,
3031  ProbingParserDummyForTesting, NULL);
3032  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_FTP, 7, 15, STREAM_TOSERVER,
3033  ProbingParserDummyForTesting, NULL);
3034  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_SMTP, 12, 0, STREAM_TOSERVER,
3035  ProbingParserDummyForTesting, NULL);
3036  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_TLS, 12, 18, STREAM_TOSERVER,
3037  ProbingParserDummyForTesting, NULL);
3038 
3039  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_DCERPC, 9, 10, STREAM_TOSERVER,
3040  ProbingParserDummyForTesting, NULL);
3041  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_FTP, 7, 15, STREAM_TOSERVER,
3042  ProbingParserDummyForTesting, NULL);
3043  result = 1;
3044 
3045  SCAppLayerProtoDetectPPRegister(IPPROTO_UDP, "85", ALPROTO_IMAP, 12, 23, STREAM_TOSERVER,
3046  ProbingParserDummyForTesting, NULL);
3047 
3048  /* toclient */
3049  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_JABBER, 12, 23, STREAM_TOCLIENT,
3050  ProbingParserDummyForTesting, NULL);
3051  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_IRC, 12, 14, STREAM_TOCLIENT,
3052  ProbingParserDummyForTesting, NULL);
3053 
3054  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "85", ALPROTO_DCERPC, 9, 10, STREAM_TOCLIENT,
3055  ProbingParserDummyForTesting, NULL);
3056  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_FTP, 7, 15, STREAM_TOCLIENT,
3057  ProbingParserDummyForTesting, NULL);
3058  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_TLS, 12, 18, STREAM_TOCLIENT,
3059  ProbingParserDummyForTesting, NULL);
3060  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3061  ProbingParserDummyForTesting, NULL);
3062  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "81", ALPROTO_DCERPC, 9, 10, STREAM_TOCLIENT,
3063  ProbingParserDummyForTesting, NULL);
3064  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "90", ALPROTO_FTP, 7, 15, STREAM_TOCLIENT,
3065  ProbingParserDummyForTesting, NULL);
3066  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_SMB, 5, 6, STREAM_TOCLIENT,
3067  ProbingParserDummyForTesting, NULL);
3068  SCAppLayerProtoDetectPPRegister(IPPROTO_UDP, "85", ALPROTO_IMAP, 12, 23, STREAM_TOCLIENT,
3069  ProbingParserDummyForTesting, NULL);
3070  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "0", ALPROTO_SMTP, 12, 17, STREAM_TOCLIENT,
3071  ProbingParserDummyForTesting, NULL);
3072  SCAppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_FTP, 7, 10, STREAM_TOCLIENT,
3073  ProbingParserDummyForTesting, NULL);
3074 
3075  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3076  { "http", ALPROTO_HTTP1, 80, 5, 8 },
3077  { "smb", ALPROTO_SMB, 80, 5, 6 },
3078  { "ftp", ALPROTO_FTP, 80, 7, 10 },
3079  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3080  { "tls", ALPROTO_TLS, 0, 12, 18 },
3081  { "irc", ALPROTO_IRC, 0, 12, 25 },
3082  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3083  };
3084  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80, 5, 8 },
3085  { "smb", ALPROTO_SMB, 80, 5, 6 }, { "ftp", ALPROTO_FTP, 80, 7, 10 },
3086  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3087  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3088 
3089  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3090  { "dcerpc", ALPROTO_DCERPC, 81, 9, 10 },
3091  { "ftp", ALPROTO_FTP, 81, 7, 15 },
3092  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3093  { "tls", ALPROTO_TLS, 0, 12, 18 },
3094  { "irc", ALPROTO_IRC, 0, 12, 25 },
3095  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3096  };
3097  AppLayerProtoDetectPPTestDataElement element_tc_81[] = { { "ftp", ALPROTO_FTP, 81, 7, 15 },
3098  { "dcerpc", ALPROTO_DCERPC, 81, 9, 10 }, { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3099  { "irc", ALPROTO_IRC, 0, 12, 14 }, { "tls", ALPROTO_TLS, 0, 12, 18 },
3100  { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3101 
3102  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3103  { "dcerpc", ALPROTO_DCERPC, 85, 9, 10 },
3104  { "ftp", ALPROTO_FTP, 85, 7, 15 },
3105  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3106  { "tls", ALPROTO_TLS, 0, 12, 18 },
3107  { "irc", ALPROTO_IRC, 0, 12, 25 },
3108  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3109  };
3110  AppLayerProtoDetectPPTestDataElement element_tc_85[] = { { "dcerpc", ALPROTO_DCERPC, 85, 9,
3111  10 },
3112  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3113  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3114 
3115  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3116  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3117  { "tls", ALPROTO_TLS, 0, 12, 18 },
3118  { "irc", ALPROTO_IRC, 0, 12, 25 },
3119  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3120  };
3121  AppLayerProtoDetectPPTestDataElement element_tc_90[] = { { "ftp", ALPROTO_FTP, 90, 7, 15 },
3122  { "jabber", ALPROTO_JABBER, 0, 12, 23 }, { "irc", ALPROTO_IRC, 0, 12, 14 },
3123  { "tls", ALPROTO_TLS, 0, 12, 18 }, { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3124 
3125  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3126  { "smtp", ALPROTO_SMTP, 0, 12, 0 },
3127  { "tls", ALPROTO_TLS, 0, 12, 18 },
3128  { "irc", ALPROTO_IRC, 0, 12, 25 },
3129  { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3130  };
3131  AppLayerProtoDetectPPTestDataElement element_tc_0[] = { { "jabber", ALPROTO_JABBER, 0, 12, 23 },
3132  { "irc", ALPROTO_IRC, 0, 12, 14 }, { "tls", ALPROTO_TLS, 0, 12, 18 },
3133  { "smtp", ALPROTO_SMTP, 0, 12, 17 } };
3134 
3135  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3136  { "imap", ALPROTO_IMAP, 85, 12, 23 },
3137  };
3138  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3139  { "imap", ALPROTO_IMAP, 85, 12, 23 },
3140  };
3141 
3142  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3143  {
3144  80,
3145  23,
3146  23,
3147  element_ts_80,
3148  element_tc_80,
3149  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3150  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3151  },
3152  {
3153  81,
3154  23,
3155  23,
3156  element_ts_81,
3157  element_tc_81,
3158  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3159  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3160  },
3161  { 85, 23, 23, element_ts_85, element_tc_85,
3162  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3163  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3164  { 90, 23, 23, element_ts_90, element_tc_90,
3165  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3166  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3167  { 0, 23, 23, element_ts_0, element_tc_0,
3168  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3169  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3170  };
3171 
3172  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3173  {
3174  85,
3175  23,
3176  23,
3177  element_ts_85_udp,
3178  element_tc_85_udp,
3179  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3180  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3181  },
3182  };
3183 
3185  { IPPROTO_TCP,
3186  ports_tcp,
3187  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3188  },
3189  { IPPROTO_UDP,
3190  ports_udp,
3191  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3192  },
3193  };
3194 
3195 
3196  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3197  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3198  goto end;
3199  }
3200  result = 1;
3201 
3202  end:
3205  return result;
3206 }
3207 
3208 
3209 /** \test test if the engine detect the proto and match with it */
3210 static int AppLayerProtoDetectTest16(void)
3211 {
3212  int result = 0;
3213  Flow *f = NULL;
3214  HtpState *http_state = NULL;
3215  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3216  "User-Agent: Mozilla/1.0\r\n"
3217  "Cookie: hellocatch\r\n\r\n";
3218  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3219  TcpSession ssn;
3220  Packet *p = NULL;
3221  Signature *s = NULL;
3222  ThreadVars tv;
3223  DetectEngineThreadCtx *det_ctx = NULL;
3224  DetectEngineCtx *de_ctx = NULL;
3226 
3227  memset(&tv, 0, sizeof(ThreadVars));
3229  memset(&ssn, 0, sizeof(TcpSession));
3230 
3231  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3232  if (p == NULL) {
3233  printf("packet setup failed: ");
3234  goto end;
3235  }
3236 
3237  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3238  if (f == NULL) {
3239  printf("flow setup failed: ");
3240  goto end;
3241  }
3242  f->protoctx = &ssn;
3243  f->proto = IPPROTO_TCP;
3244  p->flow = f;
3245 
3249 
3250  f->alproto = ALPROTO_HTTP1;
3251 
3252  StreamTcpInitConfig(true);
3253 
3255  if (de_ctx == NULL) {
3256  goto end;
3257  }
3258  de_ctx->flags |= DE_QUIET;
3259 
3260  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3261  "(msg:\"Test content option\"; "
3262  "sid:1;)");
3263  if (s == NULL) {
3264  goto end;
3265  }
3266 
3268  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3269 
3270  int r = AppLayerParserParse(
3271  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3272  if (r != 0) {
3273  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3274  goto end;
3275  }
3276 
3277  http_state = f->alstate;
3278  if (http_state == NULL) {
3279  printf("no http state: ");
3280  goto end;
3281  }
3282 
3283  /* do detect */
3284  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3285 
3286  if (!PacketAlertCheck(p, 1)) {
3287  printf("sig 1 didn't alert, but it should: ");
3288  goto end;
3289  }
3290  result = 1;
3291  end:
3292  UTHFreePackets(&p, 1);
3293  UTHFreeFlow(f);
3294  if (alp_tctx != NULL)
3296  if (det_ctx != NULL)
3297  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3298  if (de_ctx != NULL)
3300  StreamTcpFreeConfig(true);
3302  return result;
3303 }
3304 
3305 /** \test test if the engine detect the proto on a non standar port
3306  * and match with it */
3307 static int AppLayerProtoDetectTest17(void)
3308 {
3309  int result = 0;
3310  Flow *f = NULL;
3311  HtpState *http_state = NULL;
3312  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3313  "User-Agent: Mozilla/1.0\r\n"
3314  "Cookie: hellocatch\r\n\r\n";
3315  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3316  TcpSession ssn;
3317  Packet *p = NULL;
3318  Signature *s = NULL;
3319  ThreadVars tv;
3320  DetectEngineThreadCtx *det_ctx = NULL;
3321  DetectEngineCtx *de_ctx = NULL;
3323 
3324  memset(&tv, 0, sizeof(ThreadVars));
3326  memset(&ssn, 0, sizeof(TcpSession));
3327 
3328  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3329 
3330  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3331  if (f == NULL)
3332  goto end;
3333  f->protoctx = &ssn;
3334  f->proto = IPPROTO_TCP;
3335  p->flow = f;
3339  f->alproto = ALPROTO_HTTP1;
3340 
3341  StreamTcpInitConfig(true);
3342 
3344  if (de_ctx == NULL) {
3345  goto end;
3346  }
3347  de_ctx->flags |= DE_QUIET;
3348 
3349  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3350  "(msg:\"http over non standar port\"; "
3351  "sid:1;)");
3352  if (s == NULL) {
3353  goto end;
3354  }
3355 
3357  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3358 
3359  int r = AppLayerParserParse(
3360  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3361  if (r != 0) {
3362  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3363  goto end;
3364  }
3365 
3366  http_state = f->alstate;
3367  if (http_state == NULL) {
3368  printf("no http state: ");
3369  goto end;
3370  }
3371 
3372  /* do detect */
3373  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3374 
3375  if (!PacketAlertCheck(p, 1)) {
3376  printf("sig 1 didn't alert, but it should: ");
3377  goto end;
3378  }
3379 
3380  result = 1;
3381 
3382  end:
3383  UTHFreePackets(&p, 1);
3384  UTHFreeFlow(f);
3385  if (alp_tctx != NULL)
3387  if (det_ctx != NULL)
3388  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3389  if (de_ctx != NULL)
3391  StreamTcpFreeConfig(true);
3393  return result;
3394 }
3395 
3396 /** \test test if the engine detect the proto and doesn't match
3397  * because the sig expects another proto (ex ftp)*/
3398 static int AppLayerProtoDetectTest18(void)
3399 {
3400  int result = 0;
3401  Flow *f = NULL;
3402  HtpState *http_state = NULL;
3403  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3404  "User-Agent: Mozilla/1.0\r\n"
3405  "Cookie: hellocatch\r\n\r\n";
3406  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3407  TcpSession ssn;
3408  Packet *p = NULL;
3409  Signature *s = NULL;
3410  ThreadVars tv;
3411  DetectEngineThreadCtx *det_ctx = NULL;
3412  DetectEngineCtx *de_ctx = NULL;
3414 
3415  memset(&tv, 0, sizeof(ThreadVars));
3417  memset(&ssn, 0, sizeof(TcpSession));
3418 
3419  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3420 
3421  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3422  if (f == NULL)
3423  goto end;
3424  f->protoctx = &ssn;
3425  f->proto = IPPROTO_TCP;
3426  p->flow = f;
3430  f->alproto = ALPROTO_HTTP1;
3431 
3432  StreamTcpInitConfig(true);
3433 
3435  if (de_ctx == NULL) {
3436  goto end;
3437  }
3438  de_ctx->flags |= DE_QUIET;
3439 
3440  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3441  "(msg:\"Test content option\"; "
3442  "sid:1;)");
3443  if (s == NULL) {
3444  goto end;
3445  }
3446 
3448  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3449 
3450  int r = AppLayerParserParse(
3451  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3452  if (r != 0) {
3453  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3454  goto end;
3455  }
3456 
3457  http_state = f->alstate;
3458  if (http_state == NULL) {
3459  printf("no http state: ");
3460  goto end;
3461  }
3462 
3463  /* do detect */
3464  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3465 
3466  if (PacketAlertCheck(p, 1)) {
3467  printf("sig 1 alerted, but it should not (it's not ftp): ");
3468  goto end;
3469  }
3470 
3471  result = 1;
3472  end:
3473  UTHFreePackets(&p, 1);
3474  UTHFreeFlow(f);
3475  if (alp_tctx != NULL)
3477  if (det_ctx != NULL)
3478  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3479  if (de_ctx != NULL)
3481  StreamTcpFreeConfig(true);
3483  return result;
3484 }
3485 
3486 /** \test test if the engine detect the proto and doesn't match
3487  * because the packet has another proto (ex ftp) */
3488 static int AppLayerProtoDetectTest19(void)
3489 {
3490  int result = 0;
3491  Flow *f = NULL;
3492  uint8_t http_buf1[] = "MPUT one\r\n";
3493  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3494  TcpSession ssn;
3495  Packet *p = NULL;
3496  Signature *s = NULL;
3497  ThreadVars tv;
3498  DetectEngineThreadCtx *det_ctx = NULL;
3499  DetectEngineCtx *de_ctx = NULL;
3501 
3502  memset(&tv, 0, sizeof(ThreadVars));
3504  memset(&ssn, 0, sizeof(TcpSession));
3505 
3506  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3507 
3508  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3509  if (f == NULL)
3510  goto end;
3511  f->protoctx = &ssn;
3512  f->proto = IPPROTO_TCP;
3513  p->flow = f;
3517  f->alproto = ALPROTO_FTP;
3518 
3519  StreamTcpInitConfig(true);
3520 
3522  if (de_ctx == NULL) {
3523  goto end;
3524  }
3525  de_ctx->flags |= DE_QUIET;
3526 
3527  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3528  "(msg:\"http over non standar port\"; "
3529  "sid:1;)");
3530  if (s == NULL) {
3531  goto end;
3532  }
3533 
3535  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3536 
3537  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3538  STREAM_TOSERVER, http_buf1, http_buf1_len);
3539  if (r != 0) {
3540  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3541  goto end;
3542  }
3543 
3544  /* do detect */
3545  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3546 
3547  if (PacketAlertCheck(p, 1)) {
3548  printf("sig 1 alerted, but it should not (it's ftp): ");
3549  goto end;
3550  }
3551 
3552  result = 1;
3553 
3554  end:
3555  UTHFreePackets(&p, 1);
3556  UTHFreeFlow(f);
3557  if (alp_tctx != NULL)
3559  if (det_ctx != NULL)
3560  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3561  if (de_ctx != NULL)
3563  StreamTcpFreeConfig(true);
3565  return result;
3566 }
3567 
3569 {
3570  SCEnter();
3571 
3572  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3573  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3574  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3575  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3576  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3577  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3578  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3579  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3580  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3581  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3582  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3583  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3584  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3585  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3586  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3587  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3588  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3589  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3590  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3591 
3592  SCReturn;
3593 }
3594 
3595 #endif /* UNITTESTS */
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2917
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:286
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:2205
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:113
SCConfValIsTrue
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:578
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:177
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1311
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SinglePatternMatchDefaultMatcher
uint8_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition: util-spm.c: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:279
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:281
AppLayerProtoDetectProbingParserElement_::min_depth
uint16_t min_depth
Definition: app-layer-detect-proto.c:71
MpmThreadCtx_
Definition: util-mpm.h:62
stream-tcp.h
PrefilterRuleStore_::rule_id_array_cnt
uint32_t rule_id_array_cnt
Definition: util-prefilter.h:40
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c: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:223
AppLayerProtoDetectProbingParserPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:86
Flow_::proto
uint8_t proto
Definition: flow.h:377
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:144
AppLayerProtoDetectProbingParserElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c: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:562
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:355
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:69
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2197
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2910
Flow_::protomap
uint8_t protomap
Definition: flow.h:446
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its normalized string equivalent.
Definition: app-layer-protos.c:51
ctx
struct Thresholds ctx
ALPROTO_IRC
@ ALPROTO_IRC
Definition: app-layer-protos.h:45
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:987
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:457
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2878
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2086
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:356
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:232
MIN
#define MIN(x, y)
Definition: suricata-common.h:416
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:333
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:236
SCConfValIsFalse
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:603
ALPROTO_FTP
@ ALPROTO_FTP
Definition: app-layer-protos.h:37
AppLayerProtoDetectPPTestDataElement_::min_depth
uint32_t min_depth
Definition: app-layer-detect-proto.c:2913
PatIntId
#define PatIntId
Definition: suricata-common.h:343
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:243
AppLayerProtoDetectPPTestDataElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:2911
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:3064
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
p
Packet * p
Definition: fuzz_iprep.c:21
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:441
AppLayerProtoDetectPMSignature_
Definition: app-layer-detect-proto.c:108
MpmCtx_::maxdepth
uint16_t maxdepth
Definition: util-mpm.h:117
SCAppLayerForceProtocolChange
void SCAppLayerForceProtocolChange(Flow *f, AppProto new_proto)
Forces a flow app-layer protocol change. Happens for instance when a HTTP2 flow is seen as DOH2.
Definition: app-layer-detect-proto.c:1884
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:547
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:229
Flow_::protoctx
void * protoctx
Definition: flow.h:434
AppLayerProtoDetectProbingParser_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:102
AppLayerProtoDetectProbingParserPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:93
DetectPort_::port2
uint16_t port2
Definition: detect.h:224
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:114
HtpState_
Definition: app-layer-htp.h:183
FLOW_SET_PP_DONE
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:282
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:2929
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:2002
FLOW_IS_PM_DONE
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:277
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:479
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:496
AppLayerExpectationHandle
AppProto AppLayerExpectationHandle(Flow *f, uint8_t flags)
Definition: app-layer-expectation.c:304
app-layer-htp.h
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1135
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:410
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:22
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:278
DetectEngineThreadCtx_
Definition: detect.h:1306
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:425
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:71
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:3626
AppLayerProtoDetectProbingParserPort_::next
struct AppLayerProtoDetectProbingParserPort_ * next
Definition: app-layer-detect-proto.c:98
Packet_::sp
Port sp
Definition: decode.h:523
AppLayerProtoDetectReset
void AppLayerProtoDetectReset(Flow *f)
Reset proto detect for flow.
Definition: app-layer-detect-proto.c:1901
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2922
alpd_tctx
AppLayerProtoDetectThreadCtx * alpd_tctx
Definition: fuzz_applayerprotodetectgetproto.c:23
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:66
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3512
DetectPort_
Port structure for detection engine.
Definition: detect.h:222
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:2933
AppLayerProtoDetectCtx_
The app layer protocol detection context.
Definition: app-layer-detect-proto.c:144
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:325
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:285
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:100
AppLayerProtoDetectPPTestDataPort_::toclient_element
AppLayerProtoDetectPPTestDataElement * toclient_element
Definition: app-layer-detect-proto.c:2923
Packet_
Definition: decode.h:516
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:176
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:174
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:2178
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2925
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:2919
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:428
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:2918
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:200
AppLayerProtoDetectPMCtx_::mpm_ctx
MpmCtx mpm_ctx
Definition: app-layer-detect-proto.c: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:460
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:292
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:2300
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:427
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1333
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:501
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:329
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:850
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:564
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:866
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:1554
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:2930
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:120
AppLayerProtoDetectPMSignature
struct AppLayerProtoDetectPMSignature_ AppLayerProtoDetectPMSignature
FLOW_RESET_PE_DONE
#define FLOW_RESET_PE_DONE(f, dir)
Definition: flow.h:287
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:453
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3871
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:936
FatalError
#define FatalError(...)
Definition: util-debug.h:517
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:997
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:34
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:2148
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:3568
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:2914
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:2007
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2106
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:184
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
MpmTableElmt_::Prepare
int(* Prepare)(MpmConfig *, struct MpmCtx_ *)
Definition: util-mpm.h:193
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:172
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alproto_ts
AppProto alproto_ts
Definition: flow.h:452
Flow_::alstate
void * alstate
Definition: flow.h:480
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:688
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:67
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:77
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, MpmCtx *mpm_ctx, uint16_t matcher)
Definition: util-mpm.c:195
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:234
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2839
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:1919
AppLayerProtoDetectPPTestDataPort_::ts_no_of_element
int ts_no_of_element
Definition: app-layer-detect-proto.c:2924
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:2060
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:989
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:196
MpmCtx_
Definition: util-mpm.h:111
TcpSession_
Definition: stream-tcp-private.h:283
AppLayerProtoDetectProbingParser
struct AppLayerProtoDetectProbingParser_ AppLayerProtoDetectProbingParser
flow.h
AppLayerProtoDetectCtx_::expectation_proto
uint8_t * expectation_proto
Definition: app-layer-detect-proto.c:166
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:453
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:283
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:451
Packet_::dp
Port dp
Definition: decode.h:531
AppLayerProtoDetectCtx_::ctx_pp
AppLayerProtoDetectProbingParser * ctx_pp
Definition: app-layer-detect-proto.c:153
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:2912
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
SCConfNode_
Definition: conf.h:37
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1429
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:2920
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:109
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:1307
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2932
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2131
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:455
AppLayerProtoDetectPPTestDataElement_
Definition: app-layer-detect-proto.c:2909