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