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