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 ipproto, 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(1UL << (uint32_t)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, ipproto, 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 
1848 {
1849  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1850  FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
1851  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1852  FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
1853  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1854  FLOW_RESET_PE_DONE(f, STREAM_TOCLIENT);
1857 
1858  // Does not free the structures for the parser
1859  // keeps f->alstate for new state creation
1860  f->alparser = NULL;
1861  f->alproto = ALPROTO_UNKNOWN;
1864 }
1865 
1867  const char *ipproto, const char *alproto, bool default_enabled)
1868 {
1869  SCEnter();
1870 
1871  BUG_ON(ipproto == NULL || alproto == NULL);
1872 
1873  int enabled = 1;
1874  char param[100];
1875  ConfNode *node;
1876  int r;
1877 
1878  if (RunmodeIsUnittests())
1879  goto enabled;
1880 
1881 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1882  // so that fuzzig takes place for DNP3 and such
1883  default_enabled = true;
1884 #endif
1885 
1886  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1887  alproto, ".enabled");
1888  if (r < 0) {
1889  FatalError("snprintf failure.");
1890  } else if (r > (int)sizeof(param)) {
1891  FatalError("buffer not big enough to write param.");
1892  }
1893 
1894  node = ConfGetNode(param);
1895  if (node == NULL) {
1896  SCLogDebug("Entry for %s not found.", param);
1897  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1898  alproto, ".", ipproto, ".enabled");
1899  if (r < 0) {
1900  FatalError("snprintf failure.");
1901  } else if (r > (int)sizeof(param)) {
1902  FatalError("buffer not big enough to write param.");
1903  }
1904 
1905  node = ConfGetNode(param);
1906  if (node == NULL) {
1907  SCLogDebug("Entry for %s not found.", param);
1908  if (default_enabled) {
1909  goto enabled;
1910  } else {
1911  goto disabled;
1912  }
1913  }
1914  }
1915 
1916  if (node->val) {
1917  if (ConfValIsTrue(node->val)) {
1918  goto enabled;
1919  } else if (ConfValIsFalse(node->val)) {
1920  goto disabled;
1921  } else if (strcasecmp(node->val, "detection-only") == 0) {
1922  goto enabled;
1923  }
1924  }
1925 
1926  /* Invalid or null value. */
1927  SCLogError("Invalid value found for %s.", param);
1928  exit(EXIT_FAILURE);
1929 
1930  disabled:
1931  enabled = 0;
1932  enabled:
1933  SCReturnInt(enabled);
1934 }
1935 
1936 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
1937 {
1938  return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
1939 }
1940 
1942 {
1943  SCEnter();
1944 
1946  MpmCtx *mpm_ctx;
1947  MpmThreadCtx *mpm_tctx;
1948  int i, j;
1949  PatIntId max_pat_id = 0;
1950 
1951  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1952  for (j = 0; j < 2; j++) {
1953  if (max_pat_id == 0) {
1954  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1955 
1956  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1957  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1958  {
1959  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1960  }
1961  }
1962  }
1963 
1964  alpd_tctx = SCCalloc(1, sizeof(*alpd_tctx));
1965  if (alpd_tctx == NULL)
1966  goto error;
1967 
1968  /* Get the max pat id for all the mpm ctxs. */
1969  if (PmqSetup(&alpd_tctx->pmq) < 0)
1970  goto error;
1971 
1972  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1973  for (j = 0; j < 2; j++) {
1974  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1975  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1976  MpmInitThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
1977  }
1978  }
1979 
1981  if (alpd_tctx->spm_thread_ctx == NULL) {
1982  goto error;
1983  }
1984 
1985  goto end;
1986  error:
1987  if (alpd_tctx != NULL)
1989  alpd_tctx = NULL;
1990  end:
1991  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
1992 }
1993 
1995 {
1996  SCEnter();
1997 
1998  MpmCtx *mpm_ctx;
1999  MpmThreadCtx *mpm_tctx;
2000  int ipproto_map, dir;
2001 
2002  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2003  for (dir = 0; dir < 2; dir++) {
2004  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2005  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2006  MpmDestroyThreadCtx(mpm_tctx, mpm_ctx->mpm_type);
2007  }
2008  }
2009  PmqFree(&alpd_tctx->pmq);
2010  if (alpd_tctx->spm_thread_ctx != NULL) {
2012  }
2013  SCFree(alpd_tctx);
2014 
2015  SCReturn;
2016 }
2017 
2018 /***** Utility *****/
2019 
2020 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2021 {
2022  SCEnter();
2023 
2024  // Custom case for only signature-only protocol so far
2025  if (alproto == ALPROTO_HTTP) {
2028  } else {
2029  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2030  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2031  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2032  }
2033 
2034  SCReturn;
2035 }
2036 
2038 {
2039  SCEnter();
2040 
2041  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2042  while (cur_alias != NULL) {
2043  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2044  alproto_name = cur_alias->proto_name;
2045  }
2046 
2047  cur_alias = cur_alias->next;
2048  }
2049 
2050  AppProto a;
2051  AppProto b = StringToAppProto(alproto_name);
2052  for (a = 0; a < ALPROTO_MAX; a++) {
2053  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2054  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2055  SCReturnCT(b, "AppProto");
2056  }
2057  }
2058 
2059  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2060 }
2061 
2063 {
2064  // Special case for http (any version) :
2065  // returns "http" if both versions are enabled
2066  // and returns "http1" or "http2" if only one version is enabled
2067  if (alproto == ALPROTO_HTTP) {
2068  if (alpd_ctx.alproto_names[ALPROTO_HTTP1]) {
2069  if (alpd_ctx.alproto_names[ALPROTO_HTTP2]) {
2070  return "http";
2071  } // else
2072  return alpd_ctx.alproto_names[ALPROTO_HTTP1];
2073  } // else
2074  return alpd_ctx.alproto_names[ALPROTO_HTTP2];
2075  }
2076  return alpd_ctx.alproto_names[alproto];
2077 }
2078 
2080 {
2081  SCEnter();
2082 
2083  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2084 
2085  int alproto;
2086 
2087  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2088  if (alpd_ctx.alproto_names[alproto] != NULL)
2089  alprotos[alproto] = 1;
2090  }
2091 
2092  SCReturn;
2093 }
2094 
2096 
2097 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2098  uint8_t *ipprotos)
2099 {
2100  if (expectation_proto[alproto] == IPPROTO_TCP) {
2101  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2102  }
2103  if (expectation_proto[alproto] == IPPROTO_UDP) {
2104  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2105  }
2106 }
2107 
2109 {
2110  if (expectation_proto[alproto]) {
2111  if (proto != expectation_proto[alproto]) {
2112  SCLogError("Expectation on 2 IP protocols are not supported");
2113  }
2114  }
2115  expectation_proto[alproto] = proto;
2116 }
2117 
2118 /***** Unittests *****/
2119 
2120 #ifdef UNITTESTS
2121 
2122 #include "app-layer-htp.h"
2123 #include "detect-engine-alert.h"
2124 
2125 static AppLayerProtoDetectCtx alpd_ctx_ut;
2126 
2128 {
2129  SCEnter();
2130  alpd_ctx_ut = alpd_ctx;
2131  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2132  SCReturn;
2133 }
2134 
2136 {
2137  SCEnter();
2138  alpd_ctx = alpd_ctx_ut;
2139  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2140  SCReturn;
2141 }
2142 
2143 static int AppLayerProtoDetectTest01(void)
2144 {
2147 
2148  const char *buf = "HTTP";
2149  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2150  buf = "GET";
2151  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOSERVER);
2152 
2154  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2155  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2156 
2159  PASS;
2160 }
2161 
2162 static int AppLayerProtoDetectTest02(void)
2163 {
2166 
2167  const char *buf = "HTTP";
2168  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2169  buf = "ftp";
2170  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2171 
2173  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2174  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2175 
2176  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2177  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2178 
2181 
2184  PASS;
2185 }
2186 
2187 static int AppLayerProtoDetectTest03(void)
2188 {
2191 
2192  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2193  AppProto pm_results[ALPROTO_MAX];
2194  memset(pm_results, 0, sizeof(pm_results));
2195  Flow f;
2196  memset(&f, 0x00, sizeof(f));
2197  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2198 
2199 
2200  const char *buf = "HTTP";
2201  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2202  buf = "220 ";
2203  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2204 
2206  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2207  * it sets internal structures which depends on the above function. */
2210 
2211  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2212  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2213  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2214  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2217 
2218  bool rflow = false;
2219  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2220  &f, l7data, sizeof(l7data),
2221  STREAM_TOCLIENT,
2222  pm_results, &rflow);
2223  FAIL_IF(cnt != 1);
2224  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2225 
2229  PASS;
2230 }
2231 
2232 static int AppLayerProtoDetectTest04(void)
2233 {
2236 
2237  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2238  Flow f;
2239  memset(&f, 0x00, sizeof(f));
2240  AppProto pm_results[ALPROTO_MAX];
2241  memset(pm_results, 0, sizeof(pm_results));
2242  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2243 
2244  const char *buf = "200 ";
2245  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 13, 0, STREAM_TOCLIENT);
2246 
2248  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2249  * it sets internal structures which depends on the above function. */
2252 
2253  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2254  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2255  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2256  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2258 
2259  bool rdir = false;
2260  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2261  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2262  pm_results, &rdir);
2263  FAIL_IF(cnt != 1);
2264  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2265 
2269  PASS;
2270 }
2271 
2272 static int AppLayerProtoDetectTest05(void)
2273 {
2276 
2277  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2278  AppProto pm_results[ALPROTO_MAX];
2279  memset(pm_results, 0, sizeof(pm_results));
2280  Flow f;
2281  memset(&f, 0x00, sizeof(f));
2282  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2283 
2284  const char *buf = "HTTP";
2285  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2286  buf = "220 ";
2287  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2288 
2290  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2291  * it sets internal structures which depends on the above function. */
2294 
2295  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2296  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2297  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2298  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2301 
2302  bool rdir = false;
2303  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2304  &f, l7data, sizeof(l7data),
2305  STREAM_TOCLIENT,
2306  pm_results, &rdir);
2307  FAIL_IF(cnt != 1);
2308  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2309 
2313  PASS;
2314 }
2315 
2316 static int AppLayerProtoDetectTest06(void)
2317 {
2320 
2321  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2322  AppProto pm_results[ALPROTO_MAX];
2323  memset(pm_results, 0, sizeof(pm_results));
2324  Flow f;
2325  memset(&f, 0x00, sizeof(f));
2326  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2327 
2328  const char *buf = "HTTP";
2329  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2330  buf = "220 ";
2331  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_FTP, buf, 4, 0, STREAM_TOCLIENT);
2332 
2334  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2335  * it sets internal structures which depends on the above function. */
2338 
2339  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2340  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2341  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2342  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2345 
2346  bool rdir = false;
2347  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2348  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2349  pm_results, &rdir);
2350  FAIL_IF(cnt != 1);
2351  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2352 
2356  PASS;
2357 }
2358 
2359 static int AppLayerProtoDetectTest07(void)
2360 {
2363 
2364  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2365  Flow f;
2366  memset(&f, 0x00, sizeof(f));
2367  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2368  AppProto pm_results[ALPROTO_MAX];
2369  memset(pm_results, 0, sizeof(pm_results));
2370 
2371  const char *buf = "HTTP";
2372  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP1, buf, 4, 0, STREAM_TOCLIENT);
2373 
2375  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2376  * it sets internal structures which depends on the above function. */
2378 
2379  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2380  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2381  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2382  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2384 
2385  bool rdir = false;
2386  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2387  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2388  pm_results, &rdir);
2389  FAIL_IF(cnt != 0);
2390 
2394  PASS;
2395 }
2396 
2397 static int AppLayerProtoDetectTest08(void)
2398 {
2401 
2402  uint8_t l7data[] = {
2403  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2404  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2405  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2406  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2407  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2408  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2409  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2410  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2411  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2412  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2413  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2414  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2415  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2416  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2417  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2418  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2419  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2420  0x00
2421  };
2422  AppProto pm_results[ALPROTO_MAX];
2423  memset(pm_results, 0, sizeof(pm_results));
2424  Flow f;
2425  memset(&f, 0x00, sizeof(f));
2426  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2427 
2428  const char *buf = "|ff|SMB";
2429  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2430 
2432  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2433  * it sets internal structures which depends on the above function. */
2436 
2437  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2438  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2439  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2440  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2442 
2443  bool rdir = false;
2444  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2445  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2446  pm_results, &rdir);
2447  FAIL_IF(cnt != 1);
2448  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2449 
2453  PASS;
2454 }
2455 
2456 static int AppLayerProtoDetectTest09(void)
2457 {
2460 
2461  uint8_t l7data[] = {
2462  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2463  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2464  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2465  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2466  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2467  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2468  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2469  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2470  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2471  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2472  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2473  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2474  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2475  0x00, 0x02, 0x02
2476  };
2477  AppProto pm_results[ALPROTO_MAX];
2478  memset(pm_results, 0, sizeof(pm_results));
2479  Flow f;
2480  memset(&f, 0x00, sizeof(f));
2481  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2482 
2483  const char *buf = "|fe|SMB";
2484  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, buf, 8, 4, STREAM_TOCLIENT);
2485 
2487  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2488  * it sets internal structures which depends on the above function. */
2491 
2492  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2493  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2494  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2495  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2497 
2498  bool rdir = false;
2499  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2500  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2501  pm_results, &rdir);
2502  FAIL_IF(cnt != 1);
2503  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2504 
2508  PASS;
2509 }
2510 
2511 static int AppLayerProtoDetectTest10(void)
2512 {
2515 
2516  uint8_t l7data[] = {
2517  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2518  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2519  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2520  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2521  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2522  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2523  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2524  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2525  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2526  };
2527  AppProto pm_results[ALPROTO_MAX];
2528  memset(pm_results, 0, sizeof(pm_results));
2529  Flow f;
2530  memset(&f, 0x00, sizeof(f));
2531  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2532 
2533  const char *buf = "|05 00|";
2534  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC, buf, 4, 0, STREAM_TOCLIENT);
2535 
2537  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2538  * it sets internal structures which depends on the above function. */
2541 
2542  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2543  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2544  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2545  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2547 
2548  bool rdir = false;
2549  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2550  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2551  pm_results, &rdir);
2552  FAIL_IF(cnt != 1);
2553  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2554 
2558  PASS;
2559 }
2560 
2561 /**
2562  * \test Why we still get http for connect... obviously because
2563  * we also match on the reply, duh
2564  */
2565 static int AppLayerProtoDetectTest11(void)
2566 {
2569 
2570  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2571  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2572  AppProto pm_results[ALPROTO_MAX];
2573  memset(pm_results, 0, sizeof(pm_results));
2574  Flow f;
2575  memset(&f, 0x00, sizeof(f));
2576  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2577 
2579  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2581  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2583  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2585  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2587  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2589  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2591  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2593  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2594 
2596  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2597  * it sets internal structures which depends on the above function. */
2600 
2601  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2602  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2603  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2604  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2605 
2614 
2615  bool rdir = false;
2616  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2617  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2618  pm_results, &rdir);
2619  FAIL_IF(cnt != 1);
2620  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2621 
2622  memset(pm_results, 0, sizeof(pm_results));
2623  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2624  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2625  pm_results, &rdir);
2626  FAIL_IF(cnt != 1);
2627  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2628 
2632  PASS;
2633 }
2634 
2635 /**
2636  * \test AlpProtoSignature test
2637  */
2638 static int AppLayerProtoDetectTest12(void)
2639 {
2642 
2643  int r = 0;
2644 
2646  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2647  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2648  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2649  {
2650  printf("failure 1\n");
2651  goto end;
2652  }
2653 
2655  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2656  printf("failure 2\n");
2657  goto end;
2658  }
2659  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2660  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2661  {
2662  printf("failure 3\n");
2663  goto end;
2664  }
2665  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2666  printf("failure 4\n");
2667  goto end;
2668  }
2669  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2670  printf("failure 5\n");
2671  goto end;
2672  }
2673  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2674  printf("failure 6\n");
2675  goto end;
2676  }
2677 
2678  r = 1;
2679 
2680  end:
2683  return r;
2684 }
2685 
2686 /**
2687  * \test What about if we add some sigs only for udp but call for tcp?
2688  * It should not detect any proto
2689  */
2690 static int AppLayerProtoDetectTest13(void)
2691 {
2694 
2695  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2696  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2697  AppProto pm_results[ALPROTO_MAX];
2698 
2699  Flow f;
2700  memset(&f, 0x00, sizeof(f));
2701  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2702 
2704  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2706  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2708  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2710  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2712  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2714  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2716  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2718  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2719 
2721  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2722  * it sets internal structures which depends on the above function. */
2724 
2725  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2726  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2727 
2736 
2737  memset(pm_results, 0, sizeof(pm_results));
2738  bool rdir = false;
2739  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2740  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2741  pm_results, &rdir);
2742  FAIL_IF(cnt != 0);
2743 
2744  memset(pm_results, 0, sizeof(pm_results));
2745  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2746  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2747  pm_results, &rdir);
2748  FAIL_IF(cnt != 0);
2749 
2753  PASS;
2754 }
2755 
2756 /**
2757  * \test What about if we add some sigs only for udp calling it for UDP?
2758  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2759  * to ensure that TCP/UDP differences work correctly.
2760  */
2761 static int AppLayerProtoDetectTest14(void)
2762 {
2765 
2766  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2767  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2768  AppProto pm_results[ALPROTO_MAX];
2769  uint32_t cnt;
2770  Flow f;
2771  memset(&f, 0x00, sizeof(f));
2772  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2773 
2775  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2777  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2779  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2781  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2783  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2785  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2787  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2789  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2790 
2792  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2793  * it sets internal structures which depends on the above function. */
2796 
2797  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2798  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2799 
2808 
2809  memset(pm_results, 0, sizeof(pm_results));
2810  bool rdir = false;
2811  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2812  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2813  pm_results, &rdir);
2814  FAIL_IF(cnt != 1);
2815  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2816 
2817  memset(pm_results, 0, sizeof(pm_results));
2818  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2819  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2820  pm_results, &rdir);
2821  FAIL_IF(cnt != 1);
2822  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2823 
2827  PASS;
2828 }
2829 
2831  const char *alproto_name;
2833  uint16_t port;
2834  uint32_t alproto_mask;
2835  uint32_t min_depth;
2836  uint32_t max_depth;
2838 
2840  uint16_t port;
2841  uint32_t alproto_mask;
2842  uint16_t dp_max_depth;
2843  uint16_t sp_max_depth;
2844 
2850 
2851 
2853  uint8_t ipproto;
2854 
2858 
2859 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2861  int no_of_ip_proto)
2862 {
2863  int result = 0;
2864  int i = -1, j = -1 , k = -1;
2865 #ifdef DEBUG
2866  int dir = 0;
2867 #endif
2868  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2869  if (pp->ipproto != ip_proto[i].ipproto)
2870  goto end;
2871 
2873  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2874  if (pp_port->port != ip_proto[i].port[k].port)
2875  goto end;
2876  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2877  goto end;
2878  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2879  goto end;
2880  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2881  goto end;
2882  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2883  goto end;
2884 
2885  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2886 #ifdef DEBUG
2887  dir = 0;
2888 #endif
2889  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2890  j++, pp_element = pp_element->next) {
2891 
2892  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2893  goto end;
2894  }
2895  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2896  goto end;
2897  }
2898  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2899  goto end;
2900  }
2901  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2902  goto end;
2903  }
2904  } /* for */
2905  if (pp_element != NULL)
2906  goto end;
2907 
2908  pp_element = pp_port->sp;
2909 #ifdef DEBUG
2910  dir = 1;
2911 #endif
2912  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2913  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2914  goto end;
2915  }
2916  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2917  goto end;
2918  }
2919  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2920  goto end;
2921  }
2922  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2923  goto end;
2924  }
2925  } /* for */
2926  if (pp_element != NULL)
2927  goto end;
2928  }
2929  if (pp_port != NULL)
2930  goto end;
2931  }
2932  if (pp != NULL)
2933  goto end;
2934 
2935  result = 1;
2936  end:
2937 #ifdef DEBUG
2938  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2939 #endif
2940  return result;
2941 }
2942 
2943 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2944  const uint8_t *input,
2945  uint32_t input_len, uint8_t *rdir)
2946 {
2947  return 0;
2948 }
2949 
2950 static int AppLayerProtoDetectTest15(void)
2951 {
2954 
2955  int result = 0;
2956 
2957  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOSERVER,
2958  ProbingParserDummyForTesting, NULL);
2959  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2960  "80",
2961  ALPROTO_SMB,
2962  5, 6,
2963  STREAM_TOSERVER,
2964  ProbingParserDummyForTesting, NULL);
2965  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2966  "80",
2967  ALPROTO_FTP,
2968  7, 10,
2969  STREAM_TOSERVER,
2970  ProbingParserDummyForTesting, NULL);
2971 
2972  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2973  "81",
2975  9, 10,
2976  STREAM_TOSERVER,
2977  ProbingParserDummyForTesting, NULL);
2978  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2979  "81",
2980  ALPROTO_FTP,
2981  7, 15,
2982  STREAM_TOSERVER,
2983  ProbingParserDummyForTesting, NULL);
2984  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2985  "0",
2986  ALPROTO_SMTP,
2987  12, 0,
2988  STREAM_TOSERVER,
2989  ProbingParserDummyForTesting, NULL);
2990  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2991  "0",
2992  ALPROTO_TLS,
2993  12, 18,
2994  STREAM_TOSERVER,
2995  ProbingParserDummyForTesting, NULL);
2996 
2997  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2998  "85",
3000  9, 10,
3001  STREAM_TOSERVER,
3002  ProbingParserDummyForTesting, NULL);
3003  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3004  "85",
3005  ALPROTO_FTP,
3006  7, 15,
3007  STREAM_TOSERVER,
3008  ProbingParserDummyForTesting, NULL);
3009  result = 1;
3010 
3011  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3012  "85",
3013  ALPROTO_IMAP,
3014  12, 23,
3015  STREAM_TOSERVER,
3016  ProbingParserDummyForTesting, NULL);
3017 
3018  /* toclient */
3019  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3020  "0",
3022  12, 23,
3023  STREAM_TOCLIENT,
3024  ProbingParserDummyForTesting, NULL);
3025  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3026  "0",
3027  ALPROTO_IRC,
3028  12, 14,
3029  STREAM_TOCLIENT,
3030  ProbingParserDummyForTesting, NULL);
3031 
3032  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3033  "85",
3035  9, 10,
3036  STREAM_TOCLIENT,
3037  ProbingParserDummyForTesting, NULL);
3038  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3039  "81",
3040  ALPROTO_FTP,
3041  7, 15,
3042  STREAM_TOCLIENT,
3043  ProbingParserDummyForTesting, NULL);
3044  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3045  "0",
3046  ALPROTO_TLS,
3047  12, 18,
3048  STREAM_TOCLIENT,
3049  ProbingParserDummyForTesting, NULL);
3050  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "80", ALPROTO_HTTP1, 5, 8, STREAM_TOCLIENT,
3051  ProbingParserDummyForTesting, NULL);
3052  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3053  "81",
3055  9, 10,
3056  STREAM_TOCLIENT,
3057  ProbingParserDummyForTesting, NULL);
3058  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3059  "90",
3060  ALPROTO_FTP,
3061  7, 15,
3062  STREAM_TOCLIENT,
3063  ProbingParserDummyForTesting, NULL);
3064  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3065  "80",
3066  ALPROTO_SMB,
3067  5, 6,
3068  STREAM_TOCLIENT,
3069  ProbingParserDummyForTesting, NULL);
3070  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3071  "85",
3072  ALPROTO_IMAP,
3073  12, 23,
3074  STREAM_TOCLIENT,
3075  ProbingParserDummyForTesting, NULL);
3076  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3077  "0",
3078  ALPROTO_SMTP,
3079  12, 17,
3080  STREAM_TOCLIENT,
3081  ProbingParserDummyForTesting, NULL);
3082  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3083  "80",
3084  ALPROTO_FTP,
3085  7, 10,
3086  STREAM_TOCLIENT,
3087  ProbingParserDummyForTesting, NULL);
3088 
3089  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3090  { "http", ALPROTO_HTTP1, 80, 1 << ALPROTO_HTTP1, 5, 8 },
3091  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3092  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3093  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3094  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3095  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3096  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3097  };
3098  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80,
3099  1 << ALPROTO_HTTP1, 5, 8 },
3100  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3101  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3102  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3103  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3104  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3105  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 } };
3106 
3107  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3108  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3109  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3110  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3111  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3112  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3113  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3114  };
3115  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3116  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3117  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3118  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3119  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3120  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3121  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3122  };
3123 
3124  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3125  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3126  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3127  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3128  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3129  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3130  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3131  };
3132  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3133  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3134  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3135  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3136  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3137  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3138  };
3139 
3140  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3141  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3142  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3143  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3144  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3145  };
3146  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3147  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3148  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3149  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3150  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3151  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3152  };
3153 
3154  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3155  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3156  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3157  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3158  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3159  };
3160  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3161  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3162  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3163  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3164  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3165  };
3166 
3167 
3168  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3169  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3170  };
3171  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3172  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3173  };
3174 
3175  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3176  {
3177  80,
3178  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3179  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3180  (1 << ALPROTO_JABBER)),
3181  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3182  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3183  (1 << ALPROTO_SMTP)),
3184  23,
3185  element_ts_80,
3186  element_tc_80,
3187  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3188  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3189  },
3190  {
3191  81,
3192  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3193  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3194  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) |
3195  (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3196  23,
3197  element_ts_81,
3198  element_tc_81,
3199  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3200  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3201  },
3202  { 85,
3203  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3204  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3205  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3206  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3207  23, element_ts_85, element_tc_85,
3208  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3209  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3210  { 90,
3211  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3212  (1 << ALPROTO_JABBER)),
3213  ((1 << ALPROTO_FTP) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3214  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3215  23, element_ts_90, element_tc_90,
3216  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3217  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3218  { 0,
3219  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3220  (1 << ALPROTO_JABBER)),
3221  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3222  (1 << ALPROTO_SMTP)),
3223  23, element_ts_0, element_tc_0,
3224  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3225  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3226  };
3227 
3228  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3229  { 85,
3230  (1 << ALPROTO_IMAP),
3231  (1 << ALPROTO_IMAP),
3232  23,
3233  element_ts_85_udp, element_tc_85_udp,
3234  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3235  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3236  },
3237  };
3238 
3240  { IPPROTO_TCP,
3241  ports_tcp,
3242  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3243  },
3244  { IPPROTO_UDP,
3245  ports_udp,
3246  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3247  },
3248  };
3249 
3250 
3251  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3252  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3253  goto end;
3254  }
3255  result = 1;
3256 
3257  end:
3260  return result;
3261 }
3262 
3263 
3264 /** \test test if the engine detect the proto and match with it */
3265 static int AppLayerProtoDetectTest16(void)
3266 {
3267  int result = 0;
3268  Flow *f = NULL;
3269  HtpState *http_state = NULL;
3270  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3271  "User-Agent: Mozilla/1.0\r\n"
3272  "Cookie: hellocatch\r\n\r\n";
3273  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3274  TcpSession ssn;
3275  Packet *p = NULL;
3276  Signature *s = NULL;
3277  ThreadVars tv;
3278  DetectEngineThreadCtx *det_ctx = NULL;
3279  DetectEngineCtx *de_ctx = NULL;
3281 
3282  memset(&tv, 0, sizeof(ThreadVars));
3283  memset(&ssn, 0, sizeof(TcpSession));
3284 
3285  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3286  if (p == NULL) {
3287  printf("packet setup failed: ");
3288  goto end;
3289  }
3290 
3291  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3292  if (f == NULL) {
3293  printf("flow setup failed: ");
3294  goto end;
3295  }
3296  f->protoctx = &ssn;
3297  f->proto = IPPROTO_TCP;
3298  p->flow = f;
3299 
3303 
3304  f->alproto = ALPROTO_HTTP1;
3305 
3306  StreamTcpInitConfig(true);
3307 
3309  if (de_ctx == NULL) {
3310  goto end;
3311  }
3312  de_ctx->flags |= DE_QUIET;
3313 
3314  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3315  "(msg:\"Test content option\"; "
3316  "sid:1;)");
3317  if (s == NULL) {
3318  goto end;
3319  }
3320 
3322  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3323 
3324  int r = AppLayerParserParse(
3325  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3326  if (r != 0) {
3327  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3328  goto end;
3329  }
3330 
3331  http_state = f->alstate;
3332  if (http_state == NULL) {
3333  printf("no http state: ");
3334  goto end;
3335  }
3336 
3337  /* do detect */
3338  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3339 
3340  if (!PacketAlertCheck(p, 1)) {
3341  printf("sig 1 didn't alert, but it should: ");
3342  goto end;
3343  }
3344  result = 1;
3345  end:
3346  if (alp_tctx != NULL)
3348  if (det_ctx != NULL)
3349  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3350  if (de_ctx != NULL)
3352  if (de_ctx != NULL)
3354 
3355  StreamTcpFreeConfig(true);
3356 
3357  UTHFreePackets(&p, 1);
3358  UTHFreeFlow(f);
3359  return result;
3360 }
3361 
3362 /** \test test if the engine detect the proto on a non standar port
3363  * and match with it */
3364 static int AppLayerProtoDetectTest17(void)
3365 {
3366  int result = 0;
3367  Flow *f = NULL;
3368  HtpState *http_state = NULL;
3369  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3370  "User-Agent: Mozilla/1.0\r\n"
3371  "Cookie: hellocatch\r\n\r\n";
3372  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3373  TcpSession ssn;
3374  Packet *p = NULL;
3375  Signature *s = NULL;
3376  ThreadVars tv;
3377  DetectEngineThreadCtx *det_ctx = NULL;
3378  DetectEngineCtx *de_ctx = NULL;
3380 
3381  memset(&tv, 0, sizeof(ThreadVars));
3382  memset(&ssn, 0, sizeof(TcpSession));
3383 
3384  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3385 
3386  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3387  if (f == NULL)
3388  goto end;
3389  f->protoctx = &ssn;
3390  f->proto = IPPROTO_TCP;
3391  p->flow = f;
3395  f->alproto = ALPROTO_HTTP1;
3396 
3397  StreamTcpInitConfig(true);
3398 
3400  if (de_ctx == NULL) {
3401  goto end;
3402  }
3403  de_ctx->flags |= DE_QUIET;
3404 
3405  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3406  "(msg:\"http over non standar port\"; "
3407  "sid:1;)");
3408  if (s == NULL) {
3409  goto end;
3410  }
3411 
3413  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3414 
3415  int r = AppLayerParserParse(
3416  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3417  if (r != 0) {
3418  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3419  goto end;
3420  }
3421 
3422  http_state = f->alstate;
3423  if (http_state == NULL) {
3424  printf("no http state: ");
3425  goto end;
3426  }
3427 
3428  /* do detect */
3429  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3430 
3431  if (!PacketAlertCheck(p, 1)) {
3432  printf("sig 1 didn't alert, but it should: ");
3433  goto end;
3434  }
3435 
3436  result = 1;
3437 
3438  end:
3439  if (alp_tctx != NULL)
3441  if (det_ctx != NULL)
3442  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3443  if (de_ctx != NULL)
3445  if (de_ctx != NULL)
3447 
3448  StreamTcpFreeConfig(true);
3449 
3450  UTHFreePackets(&p, 1);
3451  UTHFreeFlow(f);
3452  return result;
3453 }
3454 
3455 /** \test test if the engine detect the proto and doesn't match
3456  * because the sig expects another proto (ex ftp)*/
3457 static int AppLayerProtoDetectTest18(void)
3458 {
3459  int result = 0;
3460  Flow *f = NULL;
3461  HtpState *http_state = NULL;
3462  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3463  "User-Agent: Mozilla/1.0\r\n"
3464  "Cookie: hellocatch\r\n\r\n";
3465  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3466  TcpSession ssn;
3467  Packet *p = NULL;
3468  Signature *s = NULL;
3469  ThreadVars tv;
3470  DetectEngineThreadCtx *det_ctx = NULL;
3471  DetectEngineCtx *de_ctx = NULL;
3473 
3474  memset(&tv, 0, sizeof(ThreadVars));
3475  memset(&ssn, 0, sizeof(TcpSession));
3476 
3477  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3478 
3479  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3480  if (f == NULL)
3481  goto end;
3482  f->protoctx = &ssn;
3483  f->proto = IPPROTO_TCP;
3484  p->flow = f;
3488  f->alproto = ALPROTO_HTTP1;
3489 
3490  StreamTcpInitConfig(true);
3491 
3493  if (de_ctx == NULL) {
3494  goto end;
3495  }
3496  de_ctx->flags |= DE_QUIET;
3497 
3498  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3499  "(msg:\"Test content option\"; "
3500  "sid:1;)");
3501  if (s == NULL) {
3502  goto end;
3503  }
3504 
3506  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3507 
3508  int r = AppLayerParserParse(
3509  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3510  if (r != 0) {
3511  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3512  goto end;
3513  }
3514 
3515  http_state = f->alstate;
3516  if (http_state == NULL) {
3517  printf("no http state: ");
3518  goto end;
3519  }
3520 
3521  /* do detect */
3522  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3523 
3524  if (PacketAlertCheck(p, 1)) {
3525  printf("sig 1 alerted, but it should not (it's not ftp): ");
3526  goto end;
3527  }
3528 
3529  result = 1;
3530  end:
3531  if (alp_tctx != NULL)
3533  if (det_ctx != NULL)
3534  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3535  if (de_ctx != NULL)
3537  if (de_ctx != NULL)
3539 
3540  StreamTcpFreeConfig(true);
3541 
3542  UTHFreePackets(&p, 1);
3543  UTHFreeFlow(f);
3544  return result;
3545 }
3546 
3547 /** \test test if the engine detect the proto and doesn't match
3548  * because the packet has another proto (ex ftp) */
3549 static int AppLayerProtoDetectTest19(void)
3550 {
3551  int result = 0;
3552  Flow *f = NULL;
3553  uint8_t http_buf1[] = "MPUT one\r\n";
3554  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3555  TcpSession ssn;
3556  Packet *p = NULL;
3557  Signature *s = NULL;
3558  ThreadVars tv;
3559  DetectEngineThreadCtx *det_ctx = NULL;
3560  DetectEngineCtx *de_ctx = NULL;
3562 
3563  memset(&tv, 0, sizeof(ThreadVars));
3564  memset(&ssn, 0, sizeof(TcpSession));
3565 
3566  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3567 
3568  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3569  if (f == NULL)
3570  goto end;
3571  f->protoctx = &ssn;
3572  f->proto = IPPROTO_TCP;
3573  p->flow = f;
3577  f->alproto = ALPROTO_FTP;
3578 
3579  StreamTcpInitConfig(true);
3580 
3582  if (de_ctx == NULL) {
3583  goto end;
3584  }
3585  de_ctx->flags |= DE_QUIET;
3586 
3587  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3588  "(msg:\"http over non standar port\"; "
3589  "sid:1;)");
3590  if (s == NULL) {
3591  goto end;
3592  }
3593 
3595  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3596 
3597  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3598  STREAM_TOSERVER, http_buf1, http_buf1_len);
3599  if (r != 0) {
3600  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3601  goto end;
3602  }
3603 
3604  /* do detect */
3605  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3606 
3607  if (PacketAlertCheck(p, 1)) {
3608  printf("sig 1 alerted, but it should not (it's ftp): ");
3609  goto end;
3610  }
3611 
3612  result = 1;
3613 
3614  end:
3615  if (alp_tctx != NULL)
3617  if (det_ctx != NULL)
3618  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3619  if (de_ctx != NULL)
3621  if (de_ctx != NULL)
3623 
3624  StreamTcpFreeConfig(true);
3625  UTHFreePackets(&p, 1);
3626  UTHFreeFlow(f);
3627  return result;
3628 }
3629 
3631 {
3632  SCEnter();
3633 
3634  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3635  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3636  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3637  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3638  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3639  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3640  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3641  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3642  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3643  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3644  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3645  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3646  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3647  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3648  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3649  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3650  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3651  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3652  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3653 
3654  SCReturn;
3655 }
3656 
3657 #endif /* UNITTESTS */
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:196
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2839
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:282
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:2135
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
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:187
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:1022
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:275
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:277
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:373
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:81
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:474
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:351
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2127
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2831
Flow_::protomap
uint8_t protomap
Definition: flow.h:445
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:75
ALPROTO_IRC
@ ALPROTO_IRC
Definition: app-layer-protos.h:39
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:839
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:456
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2533
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2020
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:306
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:223
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
AppLayerProtoDetectPMCtx
struct AppLayerProtoDetectPMCtx_ AppLayerProtoDetectPMCtx
DE_QUIET
#define DE_QUIET
Definition: detect.h:324
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:2835
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:340
AppLayerProtoDetectPPTestDataElement_::alproto
AppProto alproto
Definition: app-layer-detect-proto.c:2832
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1897
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:417
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:468
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:219
ALPROTO_MAX
@ ALPROTO_MAX
Definition: app-layer-protos.h:76
Flow_::protoctx
void * protoctx
Definition: flow.h:441
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:2834
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:111
HtpState_
Definition: app-layer-htp.h:244
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:537
FLOW_SET_PP_DONE
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:278
util-unittest-helper.h
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2852
util-memcmp.h
FLOW_IS_PM_DONE
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:273
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_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:69
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:475
app-layer-expectation.h
app-layer-detect-proto.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:463
UTHBuildFlow
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Definition: util-unittest-helper.c:463
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:2095
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:427
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:274
DetectEngineThreadCtx_
Definition: detect.h:1095
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:95
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:1847
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:2845
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:2314
DetectPort_
Port structure for detection engine.
Definition: detect.h:217
AppLayerProtoDetectProbingParserPort_
Definition: app-layer-detect-proto.c:86
DetectContentData_::id
PatIntId id
Definition: detect-content.h:105
app-layer-parser.h
AppLayerProtoDetectPPTestDataIPProto_::no_of_port
int no_of_port
Definition: app-layer-detect-proto.c:2856
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:2218
SCReturn
#define SCReturn
Definition: util-debug.h:273
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:281
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:2846
Packet_
Definition: decode.h:437
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:171
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:169
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:2108
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2848
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:166
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:62
AppLayerProtoDetectPPTestDataPort_::dp_max_depth
uint16_t dp_max_depth
Definition: app-layer-detect-proto.c:2842
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:419
AppLayerProtoDetectPMSignature_::pp_max_depth
uint16_t pp_max_depth
Definition: app-layer-detect-proto.c:119
AppLayerProtoDetectPPTestDataPort_::port
uint16_t port
Definition: app-layer-detect-proto.c:2840
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:459
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:254
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:2149
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:418
UTHFreeFlow
void UTHFreeFlow(Flow *flow)
Definition: util-unittest-helper.c:468
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:285
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:786
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:476
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:3244
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:68
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:794
AppLayerProtoDetectPPTestDataPort_::alproto_mask
uint32_t alproto_mask
Definition: app-layer-detect-proto.c:2841
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:1286
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3454
AppLayerProtoDetectAliases_::next
struct AppLayerProtoDetectAliases_ * next
Definition: app-layer-detect-proto.c:168
AppLayerProtoDetectPPTestDataIPProto_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:2853
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:283
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:829
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:847
AppLayerProtoDetectAliases_::proto_name
const char * proto_name
Definition: app-layer-detect-proto.c:166
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:2079
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:3630
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:2836
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:1941
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2037
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:451
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:476
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:596
ConfValIsFalse
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:562
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:67
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:71
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:225
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2494
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
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:71
AppLayerProtoDetectPPTestDataPort_::ts_no_of_element
int ts_no_of_element
Definition: app-layer-detect-proto.c:2847
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:1994
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:841
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:206
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:1866
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:452
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:279
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
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:2833
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:1936
AppLayerProtoDetectPPTestDataPort_::sp_max_depth
uint16_t sp_max_depth
Definition: app-layer-detect-proto.c:2843
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:771
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:103
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:1019
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2855
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2062
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:431
AppLayerProtoDetectPPTestDataElement_
Definition: app-layer-detect-proto.c:2830