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) {
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  AppProto pm_alproto = ALPROTO_UNKNOWN;
1412 
1413  if (!FLOW_IS_PM_DONE(f, flags)) {
1414  AppProto pm_results[g_alproto_max];
1415  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(
1416  tctx, f, buf, buflen, flags, pm_results, reverse_flow);
1417  if (pm_matches > 0) {
1418  DEBUG_VALIDATE_BUG_ON(pm_matches > 1);
1419  alproto = pm_results[0];
1420 
1421  // rerun probing parser for other direction if it is unknown
1422  uint8_t reverse_dir = (flags & STREAM_TOSERVER) ? STREAM_TOCLIENT : STREAM_TOSERVER;
1423  if (FLOW_IS_PP_DONE(f, reverse_dir)) {
1424  AppProto rev_alproto = (flags & STREAM_TOSERVER) ? f->alproto_tc : f->alproto_ts;
1425  if (rev_alproto == ALPROTO_UNKNOWN) {
1426  FLOW_RESET_PP_DONE(f, reverse_dir);
1427  }
1428  }
1429 
1430  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1431  * to avoid misdetecting DNS as DCERPC. */
1432  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1433  goto end;
1434 
1435  pm_alproto = alproto;
1436 
1437  /* fall through */
1438  }
1439  }
1440 
1441  if (!FLOW_IS_PP_DONE(f, flags)) {
1442  bool rflow = false;
1443  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto, flags, &rflow);
1444  if (AppProtoIsValid(alproto)) {
1445  if (rflow) {
1446  *reverse_flow = true;
1447  }
1448  goto end;
1449  }
1450  }
1451 
1452  /* Look if flow can be found in expectation list */
1453  if (!FLOW_IS_PE_DONE(f, flags)) {
1454  alproto = AppLayerProtoDetectPEGetProto(f, flags);
1455  }
1456 
1457  end:
1458  if (!AppProtoIsValid(alproto))
1459  alproto = pm_alproto;
1460 
1461  SCReturnUInt(alproto);
1462 }
1463 
1464 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1465 {
1466  SCEnter();
1467 
1468  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1469 
1470  if (pp == NULL)
1471  goto end;
1472 
1473  while (pp != NULL) {
1474  tmp_pp = pp->next;
1475  AppLayerProtoDetectProbingParserFree(pp);
1476  pp = tmp_pp;
1477  }
1478 
1479  end:
1480  SCReturn;
1481 }
1482 
1483 static void AppLayerProtoDetectFreeAliases(void)
1484 {
1485  SCEnter();
1486 
1487  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1488  if (cur_alias == NULL)
1489  goto end;
1490 
1491  AppLayerProtoDetectAliases *next_alias = NULL;
1492  while (cur_alias != NULL) {
1493  next_alias = cur_alias->next;
1494  SCFree(cur_alias);
1495  cur_alias = next_alias;
1496  }
1497 
1498  alpda_ctx = NULL;
1499 
1500 end:
1501  SCReturn;
1502 }
1503 
1504 /***** State Preparation *****/
1505 
1507 {
1508  SCEnter();
1509 
1510  AppLayerProtoDetectPMCtx *ctx_pm;
1511  int i, j;
1512  int ret = 0;
1513 
1514  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1515  for (j = 0; j < 2; j++) {
1516  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1517 
1518  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1519  goto error;
1520 
1521  if (ctx_pm->max_sig_id == 0)
1522  continue;
1523 
1524  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1525  goto error;
1526  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1527  goto error;
1528  }
1529  }
1530 
1531 #ifdef DEBUG
1532  if (SCLogDebugEnabled()) {
1533  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1534  }
1535 #endif
1536 
1537  goto end;
1538  error:
1539  ret = -1;
1540  end:
1541  SCReturnInt(ret);
1542 }
1543 
1544 /***** PP registration *****/
1545 
1546 /** \brief register parser at a port
1547  *
1548  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1549  */
1550 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1551  const char *portstr,
1552  AppProto alproto,
1553  uint16_t min_depth, uint16_t max_depth,
1554  uint8_t direction,
1555  ProbingParserFPtr ProbingParser1,
1556  ProbingParserFPtr ProbingParser2)
1557 {
1558  SCEnter();
1559 
1560  DetectPort *head = NULL;
1561  if (portstr == NULL) {
1562  // WebSocket has a probing parser, but no port
1563  // as it works only on HTTP1 protocol upgrade
1564  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp, ipproto, false, 0, alproto,
1565  min_depth, max_depth, direction, ProbingParser1, ProbingParser2);
1566  return;
1567  }
1568  DetectPortParse(NULL,&head, portstr);
1569  DetectPort *temp_dp = head;
1570  while (temp_dp != NULL) {
1571  uint16_t port = temp_dp->port;
1572  if (port == 0 && temp_dp->port2 != 0)
1573  port++;
1574  for (;;) {
1575  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp, ipproto, true, port,
1576  alproto, min_depth, max_depth, direction, ProbingParser1, ProbingParser2);
1577  if (port == temp_dp->port2) {
1578  break;
1579  } else {
1580  port++;
1581  }
1582  }
1583  temp_dp = temp_dp->next;
1584  }
1586 
1587  SCReturn;
1588 }
1589 
1590 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1591  uint8_t ipproto,
1592  const char *alproto_name,
1593  AppProto alproto,
1594  uint16_t min_depth, uint16_t max_depth,
1595  ProbingParserFPtr ProbingParserTs,
1596  ProbingParserFPtr ProbingParserTc)
1597 {
1598  SCEnter();
1599 
1600  char param[100];
1601  int r;
1602  ConfNode *node;
1603  ConfNode *port_node = NULL;
1604  int config = 0;
1605 
1606  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1607  alproto_name, ".detection-ports");
1608  if (r < 0) {
1609  FatalError("snprintf failure.");
1610  } else if (r > (int)sizeof(param)) {
1611  FatalError("buffer not big enough to write param.");
1612  }
1613  node = ConfGetNode(param);
1614  if (node == NULL) {
1615  SCLogDebug("Entry for %s not found.", param);
1616  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1617  alproto_name, ".", ipproto_name, ".detection-ports");
1618  if (r < 0) {
1619  FatalError("snprintf failure.");
1620  } else if (r > (int)sizeof(param)) {
1621  FatalError("buffer not big enough to write param.");
1622  }
1623  node = ConfGetNode(param);
1624  if (node == NULL)
1625  goto end;
1626  }
1627 
1628  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1629  port_node = ConfNodeLookupChild(node, "dp");
1630  if (port_node == NULL)
1631  port_node = ConfNodeLookupChild(node, "toserver");
1632 
1633  if (port_node != NULL && port_node->val != NULL) {
1635  port_node->val,
1636  alproto,
1637  min_depth, max_depth,
1638  STREAM_TOSERVER, /* to indicate dp */
1639  ProbingParserTs, ProbingParserTc);
1640  }
1641 
1642  /* detect by source port of flow */
1643  port_node = ConfNodeLookupChild(node, "sp");
1644  if (port_node == NULL)
1645  port_node = ConfNodeLookupChild(node, "toclient");
1646 
1647  if (port_node != NULL && port_node->val != NULL) {
1649  port_node->val,
1650  alproto,
1651  min_depth, max_depth,
1652  STREAM_TOCLIENT, /* to indicate sp */
1653  ProbingParserTc, ProbingParserTs);
1654 
1655  }
1656 
1657  config = 1;
1658  end:
1659  SCReturnInt(config);
1660 }
1661 
1662 /***** PM registration *****/
1663 
1665  const char *pattern,
1666  uint16_t depth, uint16_t offset,
1667  uint8_t direction)
1668 {
1669  SCEnter();
1670  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1671  pattern, depth, offset,
1672  direction, 1 /* case-sensitive */,
1673  NULL, 0, 0);
1674  SCReturnInt(r);
1675 }
1676 
1678  const char *pattern, uint16_t depth, uint16_t offset,
1679  uint8_t direction,
1680  ProbingParserFPtr PPFunc,
1681  uint16_t pp_min_depth, uint16_t pp_max_depth)
1682 {
1683  SCEnter();
1684  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1685  pattern, depth, offset,
1686  direction, 1 /* case-sensitive */,
1687  PPFunc, pp_min_depth, pp_max_depth);
1688  SCReturnInt(r);
1689 }
1690 
1692  const char *pattern,
1693  uint16_t depth, uint16_t offset,
1694  uint8_t direction)
1695 {
1696  SCEnter();
1697  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1698  pattern, depth, offset,
1699  direction, 0 /* !case-sensitive */,
1700  NULL, 0, 0);
1701  SCReturnInt(r);
1702 }
1703 
1704 /***** Setup/General Registration *****/
1705 
1707 {
1708  SCEnter();
1709 
1710  int i, j;
1711 
1712  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1713 
1714  uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1715  uint8_t mpm_matcher = PatternMatchDefaultMatcher();
1716 
1717  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1718  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1719  FatalError("Unable to alloc SpmGlobalThreadCtx.");
1720  }
1721 
1722  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1723  for (j = 0; j < 2; j++) {
1724  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1725  }
1726  }
1727 
1728  alpd_ctx.alproto_names = SCCalloc(g_alproto_max, sizeof(char *));
1729  if (unlikely(alpd_ctx.alproto_names == NULL)) {
1730  FatalError("Unable to alloc alproto_names.");
1731  }
1732  // to realloc when dynamic protos are added
1733  alpd_ctx.expectation_proto = SCCalloc(g_alproto_max, sizeof(uint8_t));
1734  if (unlikely(alpd_ctx.expectation_proto == NULL)) {
1735  FatalError("Unable to alloc expectation_proto.");
1736  }
1738 
1739  SCReturnInt(0);
1740 }
1741 
1742 /**
1743  * \todo incomplete. Need more work.
1744  */
1746 {
1747  SCEnter();
1748 
1749  int ipproto_map = 0;
1750  int dir = 0;
1751  PatIntId id = 0;
1752  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1753  AppLayerProtoDetectPMSignature *sig = NULL;
1754 
1755  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1756  for (dir = 0; dir < 2; dir++) {
1757  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1758  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1759  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1760  sig = pm_ctx->map[id];
1761  AppLayerProtoDetectPMFreeSignature(sig);
1762  }
1763  SCFree(pm_ctx->map);
1764  pm_ctx->map = NULL;
1765  }
1766  }
1767 
1768  SCFree(alpd_ctx.alproto_names);
1769  alpd_ctx.alproto_names = NULL;
1770  SCFree(alpd_ctx.expectation_proto);
1771  alpd_ctx.expectation_proto = NULL;
1772 
1774 
1775  AppLayerProtoDetectFreeAliases();
1776 
1777  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1778 
1779  SCReturnInt(0);
1780 }
1781 
1782 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1783 {
1784  SCEnter();
1785 
1786  // should have just been realloced when dynamic protos is added
1787  if (alpd_ctx.alproto_names[alproto] == NULL)
1788  alpd_ctx.alproto_names[alproto] = alproto_name;
1789 
1790  SCReturn;
1791 }
1792 
1793 void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_alias)
1794 {
1795  SCEnter();
1796 
1798  if (unlikely(new_alias == NULL)) {
1799  exit(EXIT_FAILURE);
1800  }
1801 
1802  new_alias->proto_name = proto_name;
1803  new_alias->proto_alias = proto_alias;
1804  new_alias->next = NULL;
1805 
1806  if (alpda_ctx == NULL) {
1807  alpda_ctx = new_alias;
1808  } else {
1809  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
1810  while (cur_alias->next != NULL) {
1811  cur_alias = cur_alias->next;
1812  }
1813  cur_alias->next = new_alias;
1814  }
1815 
1816  SCReturn;
1817 }
1818 
1819 /** \brief request applayer to wrap up this protocol and rerun protocol
1820  * detection.
1821  *
1822  * When this is called, the old session is reset unconditionally. A
1823  * 'detect/log' flush packet is generated for both direction before
1824  * the reset, so allow for final detection and logging.
1825  *
1826  * \param f flow to act on
1827  * \param dp destination port to use in protocol detection. Set to 443
1828  * for start tls, set to the HTTP uri port for CONNECT and
1829  * set to 0 to not use it.
1830  * \param expect_proto expected protocol. AppLayer event will be set if
1831  * detected protocol differs from this.
1832  */
1833 bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1834 {
1835  if (FlowChangeProto(f)) {
1836  // If we are already changing protocols, from SMTP to TLS for instance,
1837  // and that we do not get TLS but HTTP1, which is requesting change to HTTP2,
1838  // we do not proceed the new protocol change
1839  return false;
1840  }
1842  f->protodetect_dp = dp;
1843  f->alproto_expect = expect_proto;
1845  f->alproto_orig = f->alproto;
1846  // If one side is unknown yet, set it to the other known side
1847  if (f->alproto_ts == ALPROTO_UNKNOWN) {
1848  f->alproto_ts = f->alproto;
1849  }
1850  if (f->alproto_tc == ALPROTO_UNKNOWN) {
1851  f->alproto_tc = f->alproto;
1852  }
1853  return true;
1854 }
1855 
1856 /** \brief request applayer to wrap up this protocol and rerun protocol
1857  * detection with expectation of TLS. Used by STARTTLS.
1858  *
1859  * Sets detection port to 443 to make port based TLS detection work for
1860  * SMTP, FTP etc as well.
1861  *
1862  * \param f flow to act on
1863  */
1865 {
1867 }
1868 
1869 /** \brief Forces a flow app-layer protocol change.
1870  * Happens for instance when a HTTP2 flow is seen as DOH2
1871  *
1872  * \param f flow to act on
1873  * \param new_proto new app-layer protocol
1874  */
1876 {
1877  if (new_proto != f->alproto) {
1878  f->alproto_orig = f->alproto;
1879  f->alproto = new_proto;
1880  f->alproto_ts = f->alproto;
1881  f->alproto_tc = f->alproto;
1882  }
1883 }
1884 
1886 {
1887  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1888  FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1889  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1890  FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1891  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1892  FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1895 
1896  // Does not free the structures for the parser
1897  // keeps f->alstate for new state creation
1898  f->alparser = NULL;
1899  f->alproto = ALPROTO_UNKNOWN;
1902 }
1903 
1905  const char *ipproto, const char *alproto, bool default_enabled)
1906 {
1907  SCEnter();
1908 
1909  BUG_ON(ipproto == NULL || alproto == NULL);
1910 
1911  int enabled = 1;
1912  char param[100];
1913  ConfNode *node;
1914  int r;
1915 
1916  if (RunmodeIsUnittests())
1917  goto enabled;
1918 
1919 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1920  // so that fuzzig takes place for DNP3 and such
1921  default_enabled = true;
1922 #endif
1923 
1924  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1925  alproto, ".enabled");
1926  if (r < 0) {
1927  FatalError("snprintf failure.");
1928  } else if (r > (int)sizeof(param)) {
1929  FatalError("buffer not big enough to write param.");
1930  }
1931 
1932  node = ConfGetNode(param);
1933  if (node == NULL) {
1934  SCLogDebug("Entry for %s not found.", param);
1935  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1936  alproto, ".", ipproto, ".enabled");
1937  if (r < 0) {
1938  FatalError("snprintf failure.");
1939  } else if (r > (int)sizeof(param)) {
1940  FatalError("buffer not big enough to write param.");
1941  }
1942 
1943  node = ConfGetNode(param);
1944  if (node == NULL) {
1945  SCLogDebug("Entry for %s not found.", param);
1946  if (default_enabled) {
1947  goto enabled;
1948  } else {
1949  goto disabled;
1950  }
1951  }
1952  }
1953 
1954  if (node->val) {
1955  if (ConfValIsTrue(node->val)) {
1956  goto enabled;
1957  } else if (ConfValIsFalse(node->val)) {
1958  goto disabled;
1959  } else if (strcasecmp(node->val, "detection-only") == 0) {
1960  goto enabled;
1961  }
1962  }
1963 
1964  /* Invalid or null value. */
1965  SCLogError("Invalid value found for %s.", param);
1966  exit(EXIT_FAILURE);
1967 
1968  disabled:
1969  enabled = 0;
1970  enabled:
1971  SCReturnInt(enabled);
1972 }
1973 
1974 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
1975 {
1976  return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
1977 }
1978 
1980 {
1981  SCEnter();
1982 
1984  MpmCtx *mpm_ctx;
1985  MpmThreadCtx *mpm_tctx;
1986  int i, j;
1987  PatIntId max_pat_id = 0;
1988 
1989  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1990  for (j = 0; j < 2; j++) {
1991  if (max_pat_id == 0) {
1992  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1993 
1994  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1995  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1996  {
1997  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1998  }
1999  }
2000  }
2001 
2002  alpd_tctx = SCCalloc(1, sizeof(*alpd_tctx));
2003  if (alpd_tctx == NULL)
2004  goto error;
2005 
2006  /* Get the max pat id for all the mpm ctxs. */
2007  if (PmqSetup(&alpd_tctx->pmq) < 0)
2008  goto error;
2009 
2010  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2011  for (j = 0; j < 2; j++) {
2012  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
2013  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
2014  MpmInitThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2015  }
2016  }
2017 
2019  if (alpd_tctx->spm_thread_ctx == NULL) {
2020  goto error;
2021  }
2022 
2023  goto end;
2024  error:
2025  if (alpd_tctx != NULL)
2027  alpd_tctx = NULL;
2028  end:
2029  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2030 }
2031 
2033 {
2034  SCEnter();
2035 
2036  MpmCtx *mpm_ctx;
2037  MpmThreadCtx *mpm_tctx;
2038  int ipproto_map, dir;
2039 
2040  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2041  for (dir = 0; dir < 2; dir++) {
2042  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2043  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2044  MpmDestroyThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2045  }
2046  }
2047  PmqFree(&alpd_tctx->pmq);
2048  if (alpd_tctx->spm_thread_ctx != NULL) {
2050  }
2051  SCFree(alpd_tctx);
2052 
2053  SCReturn;
2054 }
2055 
2056 /***** Utility *****/
2057 
2058 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2059 {
2060  SCEnter();
2061 
2062  // Custom case for only signature-only protocol so far
2063  if (alproto == ALPROTO_HTTP) {
2066  } else if (alproto == ALPROTO_DOH2) {
2067  // DOH2 is not detected, just HTTP2
2069  } else {
2070  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2071  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2072  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2073  }
2074 
2075  SCReturn;
2076 }
2077 
2079 {
2080  SCEnter();
2081 
2082  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2083  while (cur_alias != NULL) {
2084  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2085  alproto_name = cur_alias->proto_name;
2086  }
2087 
2088  cur_alias = cur_alias->next;
2089  }
2090 
2091  AppProto a;
2092  AppProto b = StringToAppProto(alproto_name);
2093  for (a = 0; a < g_alproto_max; a++) {
2094  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2095  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2096  SCReturnCT(b, "AppProto");
2097  }
2098  }
2099 
2100  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2101 }
2102 
2104 {
2105  // Special case for http (any version) :
2106  // returns "http" if both versions are enabled
2107  // and returns "http1" or "http2" if only one version is enabled
2108  if (alproto == ALPROTO_HTTP) {
2109  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2110  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2111  return "http";
2112  } // else
2113  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2114  } // else
2115  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2116  }
2117  return alpd_ctx.alproto_names[alproto];
2118 }
2119 
2121 {
2122  SCEnter();
2123 
2124  memset(alprotos, 0, g_alproto_max * sizeof(AppProto));
2125 
2126  int alproto;
2127 
2128  for (alproto = 0; alproto != g_alproto_max; alproto++) {
2129  if (alpd_ctx.alproto_names[alproto] != NULL)
2130  alprotos[alproto] = 1;
2131  }
2132 
2133  SCReturn;
2134 }
2135 
2136 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2137  uint8_t *ipprotos)
2138 {
2139  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_TCP) {
2140  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2141  }
2142  if (alpd_ctx.expectation_proto[alproto] == IPPROTO_UDP) {
2143  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2144  }
2145 }
2146 
2148 {
2149  if (alpd_ctx.expectation_proto[alproto]) {
2150  if (proto != alpd_ctx.expectation_proto[alproto]) {
2151  SCLogError("Expectation on 2 IP protocols are not supported");
2152  }
2153  }
2154  alpd_ctx.expectation_proto[alproto] = proto;
2155 }
2156 
2157 /***** Unittests *****/
2158 
2159 #ifdef UNITTESTS
2160 
2161 #include "app-layer-htp.h"
2162 #include "detect-engine-alert.h"
2163 
2164 static AppLayerProtoDetectCtx alpd_ctx_ut;
2165 
2167 {
2168  SCEnter();
2169  alpd_ctx_ut = alpd_ctx;
2170  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2171  SCReturn;
2172 }
2173 
2175 {
2176  SCEnter();
2177  alpd_ctx = alpd_ctx_ut;
2178  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2179  SCReturn;
2180 }
2181 
2182 static int AppLayerProtoDetectTest01(void)
2183 {
2186 
2187  const char *buf = "HTTP";
2188  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2189  buf = "GET";
2190  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2191 
2193  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2194  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2195 
2198  PASS;
2199 }
2200 
2201 static int AppLayerProtoDetectTest02(void)
2202 {
2205 
2206  const char *buf = "HTTP";
2207  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2208  buf = "ftp";
2209  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2210 
2212  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2213  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2214 
2215  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2216  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2217 
2220 
2223  PASS;
2224 }
2225 
2226 static int AppLayerProtoDetectTest03(void)
2227 {
2230 
2231  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2232  AppProto pm_results[g_alproto_max];
2233  memset(pm_results, 0, sizeof(pm_results));
2234  Flow f;
2235  memset(&f, 0x00, sizeof(f));
2236  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2237 
2238 
2239  const char *buf = "HTTP";
2240  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2241  buf = "220 ";
2242  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2243 
2245  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2246  * it sets internal structures which depends on the above function. */
2249 
2250  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2251  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2252  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2253  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2256 
2257  bool rflow = false;
2258  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2259  &f, l7data, sizeof(l7data),
2260  STREAM_TOCLIENT,
2261  pm_results, &rflow);
2262  FAIL_IF(cnt != 1);
2263  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2264 
2268  PASS;
2269 }
2270 
2271 static int AppLayerProtoDetectTest04(void)
2272 {
2275 
2276  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2277  Flow f;
2278  memset(&f, 0x00, sizeof(f));
2279  AppProto pm_results[g_alproto_max];
2280  memset(pm_results, 0, sizeof(pm_results));
2281  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2282 
2283  const char *buf = "200 ";
2284  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2285 
2287  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2288  * it sets internal structures which depends on the above function. */
2291 
2292  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2293  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2294  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2295  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2297 
2298  bool rdir = false;
2299  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2300  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2301  pm_results, &rdir);
2302  FAIL_IF(cnt != 1);
2303  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2304 
2308  PASS;
2309 }
2310 
2311 static int AppLayerProtoDetectTest05(void)
2312 {
2315 
2316  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2317  AppProto pm_results[g_alproto_max];
2318  memset(pm_results, 0, sizeof(pm_results));
2319  Flow f;
2320  memset(&f, 0x00, sizeof(f));
2321  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2322 
2323  const char *buf = "HTTP";
2324  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2325  buf = "220 ";
2326  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2327 
2329  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2330  * it sets internal structures which depends on the above function. */
2333 
2334  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2335  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2336  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2337  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2340 
2341  bool rdir = false;
2342  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2343  &f, l7data, sizeof(l7data),
2344  STREAM_TOCLIENT,
2345  pm_results, &rdir);
2346  FAIL_IF(cnt != 1);
2347  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2348 
2352  PASS;
2353 }
2354 
2355 static int AppLayerProtoDetectTest06(void)
2356 {
2359 
2360  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2361  AppProto pm_results[g_alproto_max];
2362  memset(pm_results, 0, sizeof(pm_results));
2363  Flow f;
2364  memset(&f, 0x00, sizeof(f));
2365  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2366 
2367  const char *buf = "HTTP";
2368  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2369  buf = "220 ";
2370  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2371 
2373  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2374  * it sets internal structures which depends on the above function. */
2377 
2378  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2379  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2380  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2381  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2384 
2385  bool rdir = false;
2386  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2387  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2388  pm_results, &rdir);
2389  FAIL_IF(cnt != 1);
2390  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2391 
2395  PASS;
2396 }
2397 
2398 static int AppLayerProtoDetectTest07(void)
2399 {
2402 
2403  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2404  Flow f;
2405  memset(&f, 0x00, sizeof(f));
2406  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2407  AppProto pm_results[g_alproto_max];
2408  memset(pm_results, 0, sizeof(pm_results));
2409 
2410  const char *buf = "HTTP";
2411  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2412 
2414  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2415  * it sets internal structures which depends on the above function. */
2417 
2418  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2419  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2420  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2421  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2423 
2424  bool rdir = false;
2425  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2426  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2427  pm_results, &rdir);
2428  FAIL_IF(cnt != 0);
2429 
2433  PASS;
2434 }
2435 
2436 static int AppLayerProtoDetectTest08(void)
2437 {
2440 
2441  uint8_t l7data[] = {
2442  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2443  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2444  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2445  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2446  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2447  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2448  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2449  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2450  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2451  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2452  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2453  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2454  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2455  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2456  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2457  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2458  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2459  0x00
2460  };
2461  AppProto pm_results[g_alproto_max];
2462  memset(pm_results, 0, sizeof(pm_results));
2463  Flow f;
2464  memset(&f, 0x00, sizeof(f));
2465  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2466 
2467  const char *buf = "|ff|SMB";
2468  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2469 
2471  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2472  * it sets internal structures which depends on the above function. */
2475 
2476  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2477  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2478  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2479  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2481 
2482  bool rdir = false;
2483  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2484  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2485  pm_results, &rdir);
2486  FAIL_IF(cnt != 1);
2487  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2488 
2492  PASS;
2493 }
2494 
2495 static int AppLayerProtoDetectTest09(void)
2496 {
2499 
2500  uint8_t l7data[] = {
2501  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2502  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2503  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2504  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2505  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2506  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2507  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2508  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2509  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2510  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2511  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2512  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2513  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2514  0x00, 0x02, 0x02
2515  };
2516  AppProto pm_results[g_alproto_max];
2517  memset(pm_results, 0, sizeof(pm_results));
2518  Flow f;
2519  memset(&f, 0x00, sizeof(f));
2520  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2521 
2522  const char *buf = "|fe|SMB";
2523  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2524 
2526  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2527  * it sets internal structures which depends on the above function. */
2530 
2531  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2532  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2533  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2534  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2536 
2537  bool rdir = false;
2538  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2539  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2540  pm_results, &rdir);
2541  FAIL_IF(cnt != 1);
2542  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2543 
2547  PASS;
2548 }
2549 
2550 static int AppLayerProtoDetectTest10(void)
2551 {
2554 
2555  uint8_t l7data[] = {
2556  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2557  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2558  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2559  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2560  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2561  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2562  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2563  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2564  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2565  };
2566  AppProto pm_results[g_alproto_max];
2567  memset(pm_results, 0, sizeof(pm_results));
2568  Flow f;
2569  memset(&f, 0x00, sizeof(f));
2570  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2571 
2572  const char *buf = "|05 00|";
2573  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2574 
2576  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2577  * it sets internal structures which depends on the above function. */
2580 
2581  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2582  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2583  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2584  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2586 
2587  bool rdir = false;
2588  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2589  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2590  pm_results, &rdir);
2591  FAIL_IF(cnt != 1);
2592  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2593 
2597  PASS;
2598 }
2599 
2600 /**
2601  * \test Why we still get http for connect... obviously because
2602  * we also match on the reply, duh
2603  */
2604 static int AppLayerProtoDetectTest11(void)
2605 {
2608 
2609  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2610  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2611  AppProto pm_results[g_alproto_max];
2612  memset(pm_results, 0, sizeof(pm_results));
2613  Flow f;
2614  memset(&f, 0x00, sizeof(f));
2615  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2616 
2618  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2620  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2622  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2624  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2626  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2628  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2630  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2632  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2633 
2635  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2636  * it sets internal structures which depends on the above function. */
2639 
2640  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2641  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2642  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2643  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2644 
2653 
2654  bool rdir = false;
2655  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2656  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2657  pm_results, &rdir);
2658  FAIL_IF(cnt != 1);
2659  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2660 
2661  memset(pm_results, 0, sizeof(pm_results));
2662  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2663  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2664  pm_results, &rdir);
2665  FAIL_IF(cnt != 1);
2666  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2667 
2671  PASS;
2672 }
2673 
2674 /**
2675  * \test AlpProtoSignature test
2676  */
2677 static int AppLayerProtoDetectTest12(void)
2678 {
2681 
2682  int r = 0;
2683 
2685  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2686  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2687  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2688  {
2689  printf("failure 1\n");
2690  goto end;
2691  }
2692 
2694  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2695  printf("failure 2\n");
2696  goto end;
2697  }
2698  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2699  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2700  {
2701  printf("failure 3\n");
2702  goto end;
2703  }
2704  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2705  printf("failure 4\n");
2706  goto end;
2707  }
2708  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2709  printf("failure 5\n");
2710  goto end;
2711  }
2712  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2713  printf("failure 6\n");
2714  goto end;
2715  }
2716 
2717  r = 1;
2718 
2719  end:
2722  return r;
2723 }
2724 
2725 /**
2726  * \test What about if we add some sigs only for udp but call for tcp?
2727  * It should not detect any proto
2728  */
2729 static int AppLayerProtoDetectTest13(void)
2730 {
2733 
2734  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2735  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2736  AppProto pm_results[g_alproto_max];
2737 
2738  Flow f;
2739  memset(&f, 0x00, sizeof(f));
2740  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2741 
2743  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2745  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2747  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2749  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2751  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2753  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2755  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2757  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2758 
2760  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2761  * it sets internal structures which depends on the above function. */
2763 
2764  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2765  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2766 
2775 
2776  memset(pm_results, 0, sizeof(pm_results));
2777  bool rdir = false;
2778  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2779  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2780  pm_results, &rdir);
2781  FAIL_IF(cnt != 0);
2782 
2783  memset(pm_results, 0, sizeof(pm_results));
2784  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2785  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2786  pm_results, &rdir);
2787  FAIL_IF(cnt != 0);
2788 
2792  PASS;
2793 }
2794 
2795 /**
2796  * \test What about if we add some sigs only for udp calling it for UDP?
2797  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2798  * to ensure that TCP/UDP differences work correctly.
2799  */
2800 static int AppLayerProtoDetectTest14(void)
2801 {
2804 
2805  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2806  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2807  AppProto pm_results[g_alproto_max];
2808  uint32_t cnt;
2809  Flow f;
2810  memset(&f, 0x00, sizeof(f));
2811  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2812 
2814  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2816  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2818  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2820  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2822  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2824  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2826  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2828  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2829 
2831  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2832  * it sets internal structures which depends on the above function. */
2835 
2836  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2837  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2838 
2847 
2848  memset(pm_results, 0, sizeof(pm_results));
2849  bool rdir = false;
2850  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2851  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2852  pm_results, &rdir);
2853  FAIL_IF(cnt != 1);
2854  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2855 
2856  memset(pm_results, 0, sizeof(pm_results));
2857  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2858  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2859  pm_results, &rdir);
2860  FAIL_IF(cnt != 1);
2861  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2862 
2866  PASS;
2867 }
2868 
2870  const char *alproto_name;
2872  uint16_t port;
2873  uint32_t alproto_mask;
2874  uint32_t min_depth;
2875  uint32_t max_depth;
2877 
2879  uint16_t port;
2880  uint32_t alproto_mask;
2881  uint16_t dp_max_depth;
2882  uint16_t sp_max_depth;
2883 
2889 
2890 
2892  uint8_t ipproto;
2893 
2897 
2898 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2900  int no_of_ip_proto)
2901 {
2902  int result = 0;
2903  int i = -1, j = -1 , k = -1;
2904 #ifdef DEBUG
2905  int dir = 0;
2906 #endif
2907  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2908  if (pp->ipproto != ip_proto[i].ipproto)
2909  goto end;
2910 
2912  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2913  if (pp_port->port != ip_proto[i].port[k].port)
2914  goto end;
2915  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2916  goto end;
2917  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2918  goto end;
2919  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2920  goto end;
2921  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2922  goto end;
2923 
2924  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2925 #ifdef DEBUG
2926  dir = 0;
2927 #endif
2928  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2929  j++, pp_element = pp_element->next) {
2930 
2931  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2932  goto end;
2933  }
2934  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2935  goto end;
2936  }
2937  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2938  goto end;
2939  }
2940  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2941  goto end;
2942  }
2943  } /* for */
2944  if (pp_element != NULL)
2945  goto end;
2946 
2947  pp_element = pp_port->sp;
2948 #ifdef DEBUG
2949  dir = 1;
2950 #endif
2951  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2952  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2953  goto end;
2954  }
2955  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2956  goto end;
2957  }
2958  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2959  goto end;
2960  }
2961  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2962  goto end;
2963  }
2964  } /* for */
2965  if (pp_element != NULL)
2966  goto end;
2967  }
2968  if (pp_port != NULL)
2969  goto end;
2970  }
2971  if (pp != NULL)
2972  goto end;
2973 
2974  result = 1;
2975  end:
2976 #ifdef DEBUG
2977  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2978 #endif
2979  return result;
2980 }
2981 
2982 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2983  const uint8_t *input,
2984  uint32_t input_len, uint8_t *rdir)
2985 {
2986  return 0;
2987 }
2988 
2989 static int AppLayerProtoDetectTest15(void)
2990 {
2993 
2994  int result = 0;
2995 
2996  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
2997  ProbingParserDummyForTesting, NULL);
2998  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2999  "80",
3000  ALPROTO_SMB,
3001  5, 6,
3002  STREAM_TOSERVER,
3003  ProbingParserDummyForTesting, NULL);
3004  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3005  "80",
3006  ALPROTO_FTP,
3007  7, 10,
3008  STREAM_TOSERVER,
3009  ProbingParserDummyForTesting, NULL);
3010 
3011  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3012  "81",
3014  9, 10,
3015  STREAM_TOSERVER,
3016  ProbingParserDummyForTesting, NULL);
3017  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3018  "81",
3019  ALPROTO_FTP,
3020  7, 15,
3021  STREAM_TOSERVER,
3022  ProbingParserDummyForTesting, NULL);
3023  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3024  "0",
3025  ALPROTO_SMTP,
3026  12, 0,
3027  STREAM_TOSERVER,
3028  ProbingParserDummyForTesting, NULL);
3029  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3030  "0",
3031  ALPROTO_TLS,
3032  12, 18,
3033  STREAM_TOSERVER,
3034  ProbingParserDummyForTesting, NULL);
3035 
3036  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3037  "85",
3039  9, 10,
3040  STREAM_TOSERVER,
3041  ProbingParserDummyForTesting, NULL);
3042  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3043  "85",
3044  ALPROTO_FTP,
3045  7, 15,
3046  STREAM_TOSERVER,
3047  ProbingParserDummyForTesting, NULL);
3048  result = 1;
3049 
3050  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3051  "85",
3052  ALPROTO_IMAP,
3053  12, 23,
3054  STREAM_TOSERVER,
3055  ProbingParserDummyForTesting, NULL);
3056 
3057  /* toclient */
3058  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3059  "0",
3061  12, 23,
3062  STREAM_TOCLIENT,
3063  ProbingParserDummyForTesting, NULL);
3064  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3065  "0",
3066  ALPROTO_IRC,
3067  12, 14,
3068  STREAM_TOCLIENT,
3069  ProbingParserDummyForTesting, NULL);
3070 
3071  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3072  "85",
3074  9, 10,
3075  STREAM_TOCLIENT,
3076  ProbingParserDummyForTesting, NULL);
3077  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3078  "81",
3079  ALPROTO_FTP,
3080  7, 15,
3081  STREAM_TOCLIENT,
3082  ProbingParserDummyForTesting, NULL);
3083  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3084  "0",
3085  ALPROTO_TLS,
3086  12, 18,
3087  STREAM_TOCLIENT,
3088  ProbingParserDummyForTesting, NULL);
3089  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3090  ProbingParserDummyForTesting, NULL);
3091  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3092  "81",
3094  9, 10,
3095  STREAM_TOCLIENT,
3096  ProbingParserDummyForTesting, NULL);
3097  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3098  "90",
3099  ALPROTO_FTP,
3100  7, 15,
3101  STREAM_TOCLIENT,
3102  ProbingParserDummyForTesting, NULL);
3103  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3104  "80",
3105  ALPROTO_SMB,
3106  5, 6,
3107  STREAM_TOCLIENT,
3108  ProbingParserDummyForTesting, NULL);
3109  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3110  "85",
3111  ALPROTO_IMAP,
3112  12, 23,
3113  STREAM_TOCLIENT,
3114  ProbingParserDummyForTesting, NULL);
3115  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3116  "0",
3117  ALPROTO_SMTP,
3118  12, 17,
3119  STREAM_TOCLIENT,
3120  ProbingParserDummyForTesting, NULL);
3121  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3122  "80",
3123  ALPROTO_FTP,
3124  7, 10,
3125  STREAM_TOCLIENT,
3126  ProbingParserDummyForTesting, NULL);
3127 
3128  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3129  { "http", ALPROTO_HTTP1, 80, 1 << ALPROTO_HTTP1, 5, 8 },
3130  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3131  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3132  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3133  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3134  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3135  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3136  };
3137  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80,
3138  1 << ALPROTO_HTTP1, 5, 8 },
3139  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3140  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3141  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3142  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3143  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3144  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 } };
3145 
3146  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3147  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3148  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3149  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3150  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3151  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3152  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3153  };
3154  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3155  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3156  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3157  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3158  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3159  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3160  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3161  };
3162 
3163  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3164  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3165  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3166  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3167  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3168  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3169  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3170  };
3171  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3172  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3173  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3174  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3175  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3176  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3177  };
3178 
3179  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3180  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3181  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3182  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3183  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3184  };
3185  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3186  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3187  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3188  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3189  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3190  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3191  };
3192 
3193  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3194  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3195  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3196  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3197  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3198  };
3199  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3200  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3201  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3202  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3203  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3204  };
3205 
3206 
3207  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3208  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3209  };
3210  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3211  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3212  };
3213 
3214  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3215  {
3216  80,
3217  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3218  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3219  (1 << ALPROTO_JABBER)),
3220  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3221  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3222  (1 << ALPROTO_SMTP)),
3223  23,
3224  element_ts_80,
3225  element_tc_80,
3226  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3227  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3228  },
3229  {
3230  81,
3231  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3232  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3233  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) |
3234  (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3235  23,
3236  element_ts_81,
3237  element_tc_81,
3238  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3239  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3240  },
3241  { 85,
3242  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3243  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3244  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3245  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3246  23, element_ts_85, element_tc_85,
3247  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3248  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3249  { 90,
3250  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3251  (1 << ALPROTO_JABBER)),
3252  ((1 << ALPROTO_FTP) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3253  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3254  23, element_ts_90, element_tc_90,
3255  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3256  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3257  { 0,
3258  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3259  (1 << ALPROTO_JABBER)),
3260  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3261  (1 << ALPROTO_SMTP)),
3262  23, element_ts_0, element_tc_0,
3263  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3264  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3265  };
3266 
3267  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3268  { 85,
3269  (1 << ALPROTO_IMAP),
3270  (1 << ALPROTO_IMAP),
3271  23,
3272  element_ts_85_udp, element_tc_85_udp,
3273  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3274  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3275  },
3276  };
3277 
3279  { IPPROTO_TCP,
3280  ports_tcp,
3281  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3282  },
3283  { IPPROTO_UDP,
3284  ports_udp,
3285  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3286  },
3287  };
3288 
3289 
3290  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3291  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3292  goto end;
3293  }
3294  result = 1;
3295 
3296  end:
3299  return result;
3300 }
3301 
3302 
3303 /** \test test if the engine detect the proto and match with it */
3304 static int AppLayerProtoDetectTest16(void)
3305 {
3306  int result = 0;
3307  Flow *f = NULL;
3308  HtpState *http_state = NULL;
3309  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3310  "User-Agent: Mozilla/1.0\r\n"
3311  "Cookie: hellocatch\r\n\r\n";
3312  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3313  TcpSession ssn;
3314  Packet *p = NULL;
3315  Signature *s = NULL;
3316  ThreadVars tv;
3317  DetectEngineThreadCtx *det_ctx = NULL;
3318  DetectEngineCtx *de_ctx = NULL;
3320 
3321  memset(&tv, 0, sizeof(ThreadVars));
3322  memset(&ssn, 0, sizeof(TcpSession));
3323 
3324  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3325  if (p == NULL) {
3326  printf("packet setup failed: ");
3327  goto end;
3328  }
3329 
3330  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3331  if (f == NULL) {
3332  printf("flow setup failed: ");
3333  goto end;
3334  }
3335  f->protoctx = &ssn;
3336  f->proto = IPPROTO_TCP;
3337  p->flow = f;
3338 
3342 
3343  f->alproto = ALPROTO_HTTP1;
3344 
3345  StreamTcpInitConfig(true);
3346 
3348  if (de_ctx == NULL) {
3349  goto end;
3350  }
3351  de_ctx->flags |= DE_QUIET;
3352 
3353  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3354  "(msg:\"Test content option\"; "
3355  "sid:1;)");
3356  if (s == NULL) {
3357  goto end;
3358  }
3359 
3361  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3362 
3363  int r = AppLayerParserParse(
3364  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3365  if (r != 0) {
3366  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3367  goto end;
3368  }
3369 
3370  http_state = f->alstate;
3371  if (http_state == NULL) {
3372  printf("no http state: ");
3373  goto end;
3374  }
3375 
3376  /* do detect */
3377  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3378 
3379  if (!PacketAlertCheck(p, 1)) {
3380  printf("sig 1 didn't alert, but it should: ");
3381  goto end;
3382  }
3383  result = 1;
3384  end:
3385  if (alp_tctx != NULL)
3387  if (det_ctx != NULL)
3388  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3389  if (de_ctx != NULL)
3391  if (de_ctx != NULL)
3393 
3394  StreamTcpFreeConfig(true);
3395 
3396  UTHFreePackets(&p, 1);
3397  UTHFreeFlow(f);
3398  return result;
3399 }
3400 
3401 /** \test test if the engine detect the proto on a non standar port
3402  * and match with it */
3403 static int AppLayerProtoDetectTest17(void)
3404 {
3405  int result = 0;
3406  Flow *f = NULL;
3407  HtpState *http_state = NULL;
3408  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3409  "User-Agent: Mozilla/1.0\r\n"
3410  "Cookie: hellocatch\r\n\r\n";
3411  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3412  TcpSession ssn;
3413  Packet *p = NULL;
3414  Signature *s = NULL;
3415  ThreadVars tv;
3416  DetectEngineThreadCtx *det_ctx = NULL;
3417  DetectEngineCtx *de_ctx = NULL;
3419 
3420  memset(&tv, 0, sizeof(ThreadVars));
3421  memset(&ssn, 0, sizeof(TcpSession));
3422 
3423  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3424 
3425  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3426  if (f == NULL)
3427  goto end;
3428  f->protoctx = &ssn;
3429  f->proto = IPPROTO_TCP;
3430  p->flow = f;
3434  f->alproto = ALPROTO_HTTP1;
3435 
3436  StreamTcpInitConfig(true);
3437 
3439  if (de_ctx == NULL) {
3440  goto end;
3441  }
3442  de_ctx->flags |= DE_QUIET;
3443 
3444  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3445  "(msg:\"http over non standar port\"; "
3446  "sid:1;)");
3447  if (s == NULL) {
3448  goto end;
3449  }
3450 
3452  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3453 
3454  int r = AppLayerParserParse(
3455  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3456  if (r != 0) {
3457  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3458  goto end;
3459  }
3460 
3461  http_state = f->alstate;
3462  if (http_state == NULL) {
3463  printf("no http state: ");
3464  goto end;
3465  }
3466 
3467  /* do detect */
3468  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3469 
3470  if (!PacketAlertCheck(p, 1)) {
3471  printf("sig 1 didn't alert, but it should: ");
3472  goto end;
3473  }
3474 
3475  result = 1;
3476 
3477  end:
3478  if (alp_tctx != NULL)
3480  if (det_ctx != NULL)
3481  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3482  if (de_ctx != NULL)
3484  if (de_ctx != NULL)
3486 
3487  StreamTcpFreeConfig(true);
3488 
3489  UTHFreePackets(&p, 1);
3490  UTHFreeFlow(f);
3491  return result;
3492 }
3493 
3494 /** \test test if the engine detect the proto and doesn't match
3495  * because the sig expects another proto (ex ftp)*/
3496 static int AppLayerProtoDetectTest18(void)
3497 {
3498  int result = 0;
3499  Flow *f = NULL;
3500  HtpState *http_state = NULL;
3501  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3502  "User-Agent: Mozilla/1.0\r\n"
3503  "Cookie: hellocatch\r\n\r\n";
3504  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3505  TcpSession ssn;
3506  Packet *p = NULL;
3507  Signature *s = NULL;
3508  ThreadVars tv;
3509  DetectEngineThreadCtx *det_ctx = NULL;
3510  DetectEngineCtx *de_ctx = NULL;
3512 
3513  memset(&tv, 0, sizeof(ThreadVars));
3514  memset(&ssn, 0, sizeof(TcpSession));
3515 
3516  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3517 
3518  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3519  if (f == NULL)
3520  goto end;
3521  f->protoctx = &ssn;
3522  f->proto = IPPROTO_TCP;
3523  p->flow = f;
3527  f->alproto = ALPROTO_HTTP1;
3528 
3529  StreamTcpInitConfig(true);
3530 
3532  if (de_ctx == NULL) {
3533  goto end;
3534  }
3535  de_ctx->flags |= DE_QUIET;
3536 
3537  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3538  "(msg:\"Test content option\"; "
3539  "sid:1;)");
3540  if (s == NULL) {
3541  goto end;
3542  }
3543 
3545  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3546 
3547  int r = AppLayerParserParse(
3548  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3549  if (r != 0) {
3550  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3551  goto end;
3552  }
3553 
3554  http_state = f->alstate;
3555  if (http_state == NULL) {
3556  printf("no http state: ");
3557  goto end;
3558  }
3559 
3560  /* do detect */
3561  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3562 
3563  if (PacketAlertCheck(p, 1)) {
3564  printf("sig 1 alerted, but it should not (it's not ftp): ");
3565  goto end;
3566  }
3567 
3568  result = 1;
3569  end:
3570  if (alp_tctx != NULL)
3572  if (det_ctx != NULL)
3573  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3574  if (de_ctx != NULL)
3576  if (de_ctx != NULL)
3578 
3579  StreamTcpFreeConfig(true);
3580 
3581  UTHFreePackets(&p, 1);
3582  UTHFreeFlow(f);
3583  return result;
3584 }
3585 
3586 /** \test test if the engine detect the proto and doesn't match
3587  * because the packet has another proto (ex ftp) */
3588 static int AppLayerProtoDetectTest19(void)
3589 {
3590  int result = 0;
3591  Flow *f = NULL;
3592  uint8_t http_buf1[] = "MPUT one\r\n";
3593  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3594  TcpSession ssn;
3595  Packet *p = NULL;
3596  Signature *s = NULL;
3597  ThreadVars tv;
3598  DetectEngineThreadCtx *det_ctx = NULL;
3599  DetectEngineCtx *de_ctx = NULL;
3601 
3602  memset(&tv, 0, sizeof(ThreadVars));
3603  memset(&ssn, 0, sizeof(TcpSession));
3604 
3605  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3606 
3607  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3608  if (f == NULL)
3609  goto end;
3610  f->protoctx = &ssn;
3611  f->proto = IPPROTO_TCP;
3612  p->flow = f;
3616  f->alproto = ALPROTO_FTP;
3617 
3618  StreamTcpInitConfig(true);
3619 
3621  if (de_ctx == NULL) {
3622  goto end;
3623  }
3624  de_ctx->flags |= DE_QUIET;
3625 
3626  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3627  "(msg:\"http over non standar port\"; "
3628  "sid:1;)");
3629  if (s == NULL) {
3630  goto end;
3631  }
3632 
3634  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3635 
3636  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3637  STREAM_TOSERVER, http_buf1, http_buf1_len);
3638  if (r != 0) {
3639  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3640  goto end;
3641  }
3642 
3643  /* do detect */
3644  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3645 
3646  if (PacketAlertCheck(p, 1)) {
3647  printf("sig 1 alerted, but it should not (it's ftp): ");
3648  goto end;
3649  }
3650 
3651  result = 1;
3652 
3653  end:
3654  if (alp_tctx != NULL)
3656  if (det_ctx != NULL)
3657  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3658  if (de_ctx != NULL)
3660  if (de_ctx != NULL)
3662 
3663  StreamTcpFreeConfig(true);
3664  UTHFreePackets(&p, 1);
3665  UTHFreeFlow(f);
3666  return result;
3667 }
3668 
3670 {
3671  SCEnter();
3672 
3673  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3674  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3675  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3676  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3677  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3678  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3679  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3680  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3681  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3682  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3683  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3684  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3685  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3686  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3687  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3688  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3689  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3690  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3691  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3692 
3693  SCReturn;
3694 }
3695 
3696 #endif /* UNITTESTS */
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:195
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2878
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:288
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:2174
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:1590
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:1706
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:185
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:1691
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1268
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SinglePatternMatchDefaultMatcher
uint8_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition: util-spm.c: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:281
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:283
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:1864
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:218
AppLayerProtoDetectProbingParserPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:88
Flow_::proto
uint8_t proto
Definition: flow.h:379
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:357
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2166
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2870
Flow_::protomap
uint8_t protomap
Definition: flow.h:446
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:843
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:457
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2623
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2058
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:1833
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:232
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:231
ALPROTO_FTP
@ ALPROTO_FTP
Definition: app-layer-protos.h:37
AppLayerProtoDetectPPTestDataElement_::min_depth
uint32_t min_depth
Definition: app-layer-detect-proto.c:2874
PatIntId
#define PatIntId
Definition: suricata-common.h:318
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:2871
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1981
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:442
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:219
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:2873
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:112
HtpState_
Definition: app-layer-htp.h:238
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:284
util-unittest-helper.h
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2891
util-memcmp.h
FLOW_IS_PM_DONE
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:279
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:1550
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:476
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:428
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:280
DetectEngineThreadCtx_
Definition: detect.h:1098
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:400
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:3364
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:1885
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:1677
detect-engine-port.h
AppLayerProtoDetectPPTestDataPort_::toserver_element
AppLayerProtoDetectPPTestDataElement * toserver_element
Definition: app-layer-detect-proto.c:2884
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:2314
DetectPort_
Port structure for detection engine.
Definition: detect.h:217
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:2895
AppLayerProtoDetectCtx_
The app layer protocol detection context.
Definition: app-layer-detect-proto.c:148
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
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:2213
SCReturn
#define SCReturn
Definition: util-debug.h:273
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:287
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:2885
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:176
detect-engine-build.h
ALPROTO_IMAP
@ ALPROTO_IMAP
Definition: app-layer-protos.h:41
FLOW_GET_SP
#define FLOW_GET_SP(f)
Definition: flow.h:174
stream-tcp-private.h
SCReturnUInt
#define SCReturnUInt(x)
Definition: util-debug.h: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:2147
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2887
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:1782
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:2881
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:420
AppLayerProtoDetectPMSignature_::pp_max_depth
uint16_t pp_max_depth
Definition: app-layer-detect-proto.c:119
AppLayerProtoDetectPPTestDataPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:2879
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:460
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:251
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:2146
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:419
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:2880
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:2892
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:289
AppLayerProtoDetectDeSetup
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
Definition: app-layer-detect-proto.c:1745
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
SWAP_VARS
#define SWAP_VARS(type, a, b)
Definition: suricata-common.h:428
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3591
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:851
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:1875
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:2120
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:3669
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:2875
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1979
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2078
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:452
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:477
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:603
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:234
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2584
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:1793
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:2886
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:2032
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:845
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:1664
FlowChangeProto
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition: flow.c:204
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:1904
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:315
AppLayerProtoDetectCtx_::expectation_proto
uint8_t * expectation_proto
Definition: app-layer-detect-proto.c:169
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:453
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:1506
FLOW_SET_PE_DONE
#define FLOW_SET_PE_DONE(f, dir)
Definition: flow.h:285
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:451
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:2872
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:1974
AppLayerProtoDetectPPTestDataPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:2882
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:1265
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2894
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2103
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:2869