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