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