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 *ipproto, const char *alproto, bool default_enabled)
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  if (default_enabled) {
2025  goto enabled;
2026  } else {
2027  goto disabled;
2028  }
2029  }
2030  }
2031 
2032  if (node->val) {
2033  if (ConfValIsTrue(node->val)) {
2034  goto enabled;
2035  } else if (ConfValIsFalse(node->val)) {
2036  goto disabled;
2037  } else if (strcasecmp(node->val, "detection-only") == 0) {
2038  goto enabled;
2039  }
2040  }
2041 
2042  /* Invalid or null value. */
2043  SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
2044  exit(EXIT_FAILURE);
2045 
2046  disabled:
2047  enabled = 0;
2048  enabled:
2049  SCReturnInt(enabled);
2050 }
2051 
2052 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
2053 {
2054  return AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto, alproto, true);
2055 }
2056 
2058 {
2059  SCEnter();
2060 
2062  MpmCtx *mpm_ctx;
2063  MpmThreadCtx *mpm_tctx;
2064  int i, j;
2065  PatIntId max_pat_id = 0;
2066 
2067  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2068  for (j = 0; j < 2; j++) {
2069  if (max_pat_id == 0) {
2070  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2071 
2072  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
2073  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
2074  {
2075  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
2076  }
2077  }
2078  }
2079 
2080  alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
2081  if (alpd_tctx == NULL)
2082  goto error;
2083  memset(alpd_tctx, 0, sizeof(*alpd_tctx));
2084 
2085  /* Get the max pat id for all the mpm ctxs. */
2086  if (PmqSetup(&alpd_tctx->pmq) < 0)
2087  goto error;
2088 
2089  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
2090  for (j = 0; j < 2; j++) {
2091  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
2092  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
2093  mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
2094  }
2095  }
2096 
2098  if (alpd_tctx->spm_thread_ctx == NULL) {
2099  goto error;
2100  }
2101 
2102  goto end;
2103  error:
2104  if (alpd_tctx != NULL)
2106  alpd_tctx = NULL;
2107  end:
2108  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2109 }
2110 
2112 {
2113  SCEnter();
2114 
2115  MpmCtx *mpm_ctx;
2116  MpmThreadCtx *mpm_tctx;
2117  int ipproto_map, dir;
2118 
2119  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2120  for (dir = 0; dir < 2; dir++) {
2121  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2122  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2123  mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2124  }
2125  }
2126  PmqFree(&alpd_tctx->pmq);
2127  if (alpd_tctx->spm_thread_ctx != NULL) {
2129  }
2130  SCFree(alpd_tctx);
2131 
2132  SCReturn;
2133 }
2134 
2135 /***** Utility *****/
2136 
2137 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2138 {
2139  SCEnter();
2140 
2141  // Custom case for only signature-only protocol so far
2142  if (alproto == ALPROTO_HTTP) {
2145  } else {
2146  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2147  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2148  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2149  }
2150 
2151  SCReturn;
2152 }
2153 
2155 {
2156  SCEnter();
2157 
2158  AppLayerProtoDetectAliases *cur_alias = alpda_ctx;
2159  while (cur_alias != NULL) {
2160  if (strcasecmp(alproto_name, cur_alias->proto_alias) == 0) {
2161  alproto_name = cur_alias->proto_name;
2162  }
2163 
2164  cur_alias = cur_alias->next;
2165  }
2166 
2167  AppProto a;
2168  AppProto b = StringToAppProto(alproto_name);
2169  for (a = 0; a < ALPROTO_MAX; a++) {
2170  if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) {
2171  // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled
2172  SCReturnCT(b, "AppProto");
2173  }
2174  }
2175 
2176  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2177 }
2178 
2180 {
2181  return alpd_ctx.alproto_names[alproto];
2182 }
2183 
2185 {
2186  SCEnter();
2187 
2188  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2189 
2190  int alproto;
2191 
2192  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2193  if (alpd_ctx.alproto_names[alproto] != NULL)
2194  alprotos[alproto] = 1;
2195  }
2196 
2197  SCReturn;
2198 }
2199 
2201 
2202 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2203  uint8_t *ipprotos)
2204 {
2205  if (expectation_proto[alproto] == IPPROTO_TCP) {
2206  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2207  }
2208  if (expectation_proto[alproto] == IPPROTO_UDP) {
2209  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2210  }
2211 }
2212 
2214 {
2215  if (expectation_proto[alproto]) {
2216  if (proto != expectation_proto[alproto]) {
2218  "Expectation on 2 IP protocols are not supported");
2219  }
2220  }
2221  expectation_proto[alproto] = proto;
2222 }
2223 
2224 /***** Unittests *****/
2225 
2226 #ifdef UNITTESTS
2227 
2228 #include "app-layer-htp.h"
2229 
2230 static AppLayerProtoDetectCtx alpd_ctx_ut;
2231 
2233 {
2234  SCEnter();
2235  alpd_ctx_ut = alpd_ctx;
2236  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2237  SCReturn;
2238 }
2239 
2241 {
2242  SCEnter();
2243  alpd_ctx = alpd_ctx_ut;
2244  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2245  SCReturn;
2246 }
2247 
2248 static int AppLayerProtoDetectTest01(void)
2249 {
2252 
2253  const char *buf = "HTTP";
2255  buf = "GET";
2257 
2259  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2260  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2261 
2264  PASS;
2265 }
2266 
2267 static int AppLayerProtoDetectTest02(void)
2268 {
2271 
2272  const char *buf = "HTTP";
2274  buf = "ftp";
2276 
2278  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2279  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2280 
2281  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2282  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2283 
2286 
2289  PASS;
2290 }
2291 
2292 static int AppLayerProtoDetectTest03(void)
2293 {
2296 
2297  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2298  AppProto pm_results[ALPROTO_MAX];
2299  memset(pm_results, 0, sizeof(pm_results));
2300  Flow f;
2301  memset(&f, 0x00, sizeof(f));
2302  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2303 
2304 
2305  const char *buf = "HTTP";
2307  buf = "220 ";
2309 
2311  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2312  * it sets internal structures which depends on the above function. */
2315 
2316  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2317  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2318  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2319  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2322 
2323  bool rflow = false;
2324  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2325  &f, l7data, sizeof(l7data),
2327  pm_results, &rflow);
2328  FAIL_IF(cnt != 1);
2329  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2330 
2334  PASS;
2335 }
2336 
2337 static int AppLayerProtoDetectTest04(void)
2338 {
2341 
2342  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2343  Flow f;
2344  memset(&f, 0x00, sizeof(f));
2345  AppProto pm_results[ALPROTO_MAX];
2346  memset(pm_results, 0, sizeof(pm_results));
2347  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2348 
2349  const char *buf = "200 ";
2351 
2353  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2354  * it sets internal structures which depends on the above function. */
2357 
2358  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2359  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2360  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2361  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2363 
2364  bool rdir = false;
2365  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2366  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2367  pm_results, &rdir);
2368  FAIL_IF(cnt != 1);
2369  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2370 
2374  PASS;
2375 }
2376 
2377 static int AppLayerProtoDetectTest05(void)
2378 {
2381 
2382  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2383  AppProto pm_results[ALPROTO_MAX];
2384  memset(pm_results, 0, sizeof(pm_results));
2385  Flow f;
2386  memset(&f, 0x00, sizeof(f));
2387  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2388 
2389  const char *buf = "HTTP";
2391  buf = "220 ";
2393 
2395  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2396  * it sets internal structures which depends on the above function. */
2399 
2400  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2401  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2402  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2403  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2406 
2407  bool rdir = false;
2408  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2409  &f, l7data, sizeof(l7data),
2411  pm_results, &rdir);
2412  FAIL_IF(cnt != 1);
2413  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2414 
2418  PASS;
2419 }
2420 
2421 static int AppLayerProtoDetectTest06(void)
2422 {
2425 
2426  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2427  AppProto pm_results[ALPROTO_MAX];
2428  memset(pm_results, 0, sizeof(pm_results));
2429  Flow f;
2430  memset(&f, 0x00, sizeof(f));
2431  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2432 
2433  const char *buf = "HTTP";
2435  buf = "220 ";
2437 
2439  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2440  * it sets internal structures which depends on the above function. */
2443 
2444  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2445  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2446  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2447  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2450 
2451  bool rdir = false;
2452  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2453  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2454  pm_results, &rdir);
2455  FAIL_IF(cnt != 1);
2456  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2457 
2461  PASS;
2462 }
2463 
2464 static int AppLayerProtoDetectTest07(void)
2465 {
2468 
2469  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2470  Flow f;
2471  memset(&f, 0x00, sizeof(f));
2472  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2473  AppProto pm_results[ALPROTO_MAX];
2474  memset(pm_results, 0, sizeof(pm_results));
2475 
2476  const char *buf = "HTTP";
2478 
2480  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2481  * it sets internal structures which depends on the above function. */
2483 
2484  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2485  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2486  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2487  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2489 
2490  bool rdir = false;
2491  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2492  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2493  pm_results, &rdir);
2494  FAIL_IF(cnt != 0);
2495 
2499  PASS;
2500 }
2501 
2502 static int AppLayerProtoDetectTest08(void)
2503 {
2506 
2507  uint8_t l7data[] = {
2508  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2509  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2510  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2511  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2512  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2513  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2514  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2515  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2516  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2517  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2518  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2519  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2520  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2521  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2522  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2523  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2524  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2525  0x00
2526  };
2527  AppProto pm_results[ALPROTO_MAX];
2528  memset(pm_results, 0, sizeof(pm_results));
2529  Flow f;
2530  memset(&f, 0x00, sizeof(f));
2531  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2532 
2533  const char *buf = "|ff|SMB";
2535 
2537  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2538  * it sets internal structures which depends on the above function. */
2541 
2542  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2543  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2544  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2545  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2547 
2548  bool rdir = false;
2549  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2550  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2551  pm_results, &rdir);
2552  FAIL_IF(cnt != 1);
2553  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2554 
2558  PASS;
2559 }
2560 
2561 static int AppLayerProtoDetectTest09(void)
2562 {
2565 
2566  uint8_t l7data[] = {
2567  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2568  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2569  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2570  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2571  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2572  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2573  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2574  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2575  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2576  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2577  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2578  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2579  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2580  0x00, 0x02, 0x02
2581  };
2582  AppProto pm_results[ALPROTO_MAX];
2583  memset(pm_results, 0, sizeof(pm_results));
2584  Flow f;
2585  memset(&f, 0x00, sizeof(f));
2586  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2587 
2588  const char *buf = "|fe|SMB";
2590 
2592  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2593  * it sets internal structures which depends on the above function. */
2596 
2597  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2598  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2599  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2600  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2602 
2603  bool rdir = false;
2604  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2605  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2606  pm_results, &rdir);
2607  FAIL_IF(cnt != 1);
2608  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2609 
2613  PASS;
2614 }
2615 
2616 static int AppLayerProtoDetectTest10(void)
2617 {
2620 
2621  uint8_t l7data[] = {
2622  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2623  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2624  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2625  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2626  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2627  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2628  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2629  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2630  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2631  };
2632  AppProto pm_results[ALPROTO_MAX];
2633  memset(pm_results, 0, sizeof(pm_results));
2634  Flow f;
2635  memset(&f, 0x00, sizeof(f));
2636  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2637 
2638  const char *buf = "|05 00|";
2640 
2642  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2643  * it sets internal structures which depends on the above function. */
2646 
2647  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2648  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2649  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2650  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2652 
2653  bool rdir = false;
2654  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2655  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2656  pm_results, &rdir);
2657  FAIL_IF(cnt != 1);
2658  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2659 
2663  PASS;
2664 }
2665 
2666 /**
2667  * \test Why we still get http for connect... obviously because
2668  * we also match on the reply, duh
2669  */
2670 static int AppLayerProtoDetectTest11(void)
2671 {
2674 
2675  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2676  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2677  AppProto pm_results[ALPROTO_MAX];
2678  memset(pm_results, 0, sizeof(pm_results));
2679  Flow f;
2680  memset(&f, 0x00, sizeof(f));
2681  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2682 
2684  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2686  IPPROTO_TCP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2688  IPPROTO_TCP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2690  IPPROTO_TCP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2692  IPPROTO_TCP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2694  IPPROTO_TCP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2696  IPPROTO_TCP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2698  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2699 
2701  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2702  * it sets internal structures which depends on the above function. */
2705 
2706  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2707  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2708  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2709  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2710 
2719 
2720  bool rdir = false;
2721  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2722  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2723  pm_results, &rdir);
2724  FAIL_IF(cnt != 1);
2725  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2726 
2727  memset(pm_results, 0, sizeof(pm_results));
2728  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2729  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2730  pm_results, &rdir);
2731  FAIL_IF(cnt != 1);
2732  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2733 
2737  PASS;
2738 }
2739 
2740 /**
2741  * \test AlpProtoSignature test
2742  */
2743 static int AppLayerProtoDetectTest12(void)
2744 {
2747 
2748  int r = 0;
2749 
2751  IPPROTO_TCP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2752  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2753  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2754  {
2755  printf("failure 1\n");
2756  goto end;
2757  }
2758 
2760  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2761  printf("failure 2\n");
2762  goto end;
2763  }
2764  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2765  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2766  {
2767  printf("failure 3\n");
2768  goto end;
2769  }
2770  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP1) {
2771  printf("failure 4\n");
2772  goto end;
2773  }
2774  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2775  printf("failure 5\n");
2776  goto end;
2777  }
2778  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2779  printf("failure 6\n");
2780  goto end;
2781  }
2782 
2783  r = 1;
2784 
2785  end:
2788  return r;
2789 }
2790 
2791 /**
2792  * \test What about if we add some sigs only for udp but call for tcp?
2793  * It should not detect any proto
2794  */
2795 static int AppLayerProtoDetectTest13(void)
2796 {
2799 
2800  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2801  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2802  AppProto pm_results[ALPROTO_MAX];
2803 
2804  Flow f;
2805  memset(&f, 0x00, sizeof(f));
2806  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2807 
2809  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2811  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2813  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2815  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2817  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2819  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2821  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2823  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2824 
2826  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2827  * it sets internal structures which depends on the above function. */
2829 
2830  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2831  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2832 
2841 
2842  memset(pm_results, 0, sizeof(pm_results));
2843  bool rdir = false;
2844  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2845  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2846  pm_results, &rdir);
2847  FAIL_IF(cnt != 0);
2848 
2849  memset(pm_results, 0, sizeof(pm_results));
2850  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2851  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2852  pm_results, &rdir);
2853  FAIL_IF(cnt != 0);
2854 
2858  PASS;
2859 }
2860 
2861 /**
2862  * \test What about if we add some sigs only for udp calling it for UDP?
2863  * It should detect ALPROTO_HTTP1 (over udp). This is just a check
2864  * to ensure that TCP/UDP differences work correctly.
2865  */
2866 static int AppLayerProtoDetectTest14(void)
2867 {
2870 
2871  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2872  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2873  AppProto pm_results[ALPROTO_MAX];
2874  uint32_t cnt;
2875  Flow f;
2876  memset(&f, 0x00, sizeof(f));
2877  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2878 
2880  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOSERVER);
2882  IPPROTO_UDP, ALPROTO_HTTP1, "GET", 3, 0, STREAM_TOSERVER);
2884  IPPROTO_UDP, ALPROTO_HTTP1, "PUT", 3, 0, STREAM_TOSERVER);
2886  IPPROTO_UDP, ALPROTO_HTTP1, "POST", 4, 0, STREAM_TOSERVER);
2888  IPPROTO_UDP, ALPROTO_HTTP1, "TRACE", 5, 0, STREAM_TOSERVER);
2890  IPPROTO_UDP, ALPROTO_HTTP1, "OPTIONS", 7, 0, STREAM_TOSERVER);
2892  IPPROTO_UDP, ALPROTO_HTTP1, "CONNECT", 7, 0, STREAM_TOSERVER);
2894  IPPROTO_UDP, ALPROTO_HTTP1, "HTTP", 4, 0, STREAM_TOCLIENT);
2895 
2897  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2898  * it sets internal structures which depends on the above function. */
2901 
2902  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2903  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2904 
2913 
2914  memset(pm_results, 0, sizeof(pm_results));
2915  bool rdir = false;
2916  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2917  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2918  pm_results, &rdir);
2919  FAIL_IF(cnt != 1);
2920  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2921 
2922  memset(pm_results, 0, sizeof(pm_results));
2923  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2924  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2925  pm_results, &rdir);
2926  FAIL_IF(cnt != 1);
2927  FAIL_IF(pm_results[0] != ALPROTO_HTTP1);
2928 
2932  PASS;
2933 }
2934 
2936  const char *alproto_name;
2938  uint16_t port;
2939  uint32_t alproto_mask;
2940  uint32_t min_depth;
2941  uint32_t max_depth;
2943 
2945  uint16_t port;
2946  uint32_t alproto_mask;
2947  uint16_t dp_max_depth;
2948  uint16_t sp_max_depth;
2949 
2955 
2956 
2958  uint8_t ipproto;
2959 
2963 
2964 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2966  int no_of_ip_proto)
2967 {
2968  int result = 0;
2969  int i = -1, j = -1 , k = -1;
2970 #ifdef DEBUG
2971  int dir = 0;
2972 #endif
2973  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2974  if (pp->ipproto != ip_proto[i].ipproto)
2975  goto end;
2976 
2978  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2979  if (pp_port->port != ip_proto[i].port[k].port)
2980  goto end;
2981  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2982  goto end;
2983  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2984  goto end;
2985  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2986  goto end;
2987  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2988  goto end;
2989 
2990  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2991 #ifdef DEBUG
2992  dir = 0;
2993 #endif
2994  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2995  j++, pp_element = pp_element->next) {
2996 
2997  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2998  goto end;
2999  }
3000  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
3001  goto end;
3002  }
3003  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
3004  goto end;
3005  }
3006  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
3007  goto end;
3008  }
3009  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
3010  goto end;
3011  }
3012  } /* for */
3013  if (pp_element != NULL)
3014  goto end;
3015 
3016  pp_element = pp_port->sp;
3017 #ifdef DEBUG
3018  dir = 1;
3019 #endif
3020  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
3021  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
3022  goto end;
3023  }
3024  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
3025  goto end;
3026  }
3027  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
3028  goto end;
3029  }
3030  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
3031  goto end;
3032  }
3033  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
3034  goto end;
3035  }
3036  } /* for */
3037  if (pp_element != NULL)
3038  goto end;
3039  }
3040  if (pp_port != NULL)
3041  goto end;
3042  }
3043  if (pp != NULL)
3044  goto end;
3045 
3046  result = 1;
3047  end:
3048 #ifdef DEBUG
3049  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
3050 #endif
3051  return result;
3052 }
3053 
3054 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
3055  const uint8_t *input,
3056  uint32_t input_len, uint8_t *rdir)
3057 {
3058  return 0;
3059 }
3060 
3061 static int AppLayerProtoDetectTest15(void)
3062 {
3065 
3066  int result = 0;
3067 
3069  ProbingParserDummyForTesting, NULL);
3070  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3071  "80",
3072  ALPROTO_SMB,
3073  5, 6,
3075  ProbingParserDummyForTesting, NULL);
3076  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3077  "80",
3078  ALPROTO_FTP,
3079  7, 10,
3081  ProbingParserDummyForTesting, NULL);
3082 
3083  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3084  "81",
3086  9, 10,
3088  ProbingParserDummyForTesting, NULL);
3089  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3090  "81",
3091  ALPROTO_FTP,
3092  7, 15,
3094  ProbingParserDummyForTesting, NULL);
3095  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3096  "0",
3097  ALPROTO_SMTP,
3098  12, 0,
3100  ProbingParserDummyForTesting, NULL);
3101  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3102  "0",
3103  ALPROTO_TLS,
3104  12, 18,
3106  ProbingParserDummyForTesting, NULL);
3107 
3108  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3109  "85",
3111  9, 10,
3113  ProbingParserDummyForTesting, NULL);
3114  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3115  "85",
3116  ALPROTO_FTP,
3117  7, 15,
3119  ProbingParserDummyForTesting, NULL);
3120  result = 1;
3121 
3122  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3123  "85",
3124  ALPROTO_IMAP,
3125  12, 23,
3127  ProbingParserDummyForTesting, NULL);
3128 
3129  /* toclient */
3130  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3131  "0",
3133  12, 23,
3135  ProbingParserDummyForTesting, NULL);
3136  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3137  "0",
3138  ALPROTO_IRC,
3139  12, 14,
3141  ProbingParserDummyForTesting, NULL);
3142 
3143  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3144  "85",
3146  9, 10,
3148  ProbingParserDummyForTesting, NULL);
3149  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3150  "81",
3151  ALPROTO_FTP,
3152  7, 15,
3154  ProbingParserDummyForTesting, NULL);
3155  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3156  "0",
3157  ALPROTO_TLS,
3158  12, 18,
3160  ProbingParserDummyForTesting, NULL);
3162  ProbingParserDummyForTesting, NULL);
3163  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3164  "81",
3166  9, 10,
3168  ProbingParserDummyForTesting, NULL);
3169  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3170  "90",
3171  ALPROTO_FTP,
3172  7, 15,
3174  ProbingParserDummyForTesting, NULL);
3175  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3176  "80",
3177  ALPROTO_SMB,
3178  5, 6,
3180  ProbingParserDummyForTesting, NULL);
3181  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3182  "85",
3183  ALPROTO_IMAP,
3184  12, 23,
3186  ProbingParserDummyForTesting, NULL);
3187  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3188  "0",
3189  ALPROTO_SMTP,
3190  12, 17,
3192  ProbingParserDummyForTesting, NULL);
3193  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3194  "80",
3195  ALPROTO_FTP,
3196  7, 10,
3198  ProbingParserDummyForTesting, NULL);
3199 
3200  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3201  { "http", ALPROTO_HTTP1, 80, 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  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3205  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3206  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3207  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3208  };
3209  AppLayerProtoDetectPPTestDataElement element_tc_80[] = { { "http", ALPROTO_HTTP1, 80,
3210  1 << ALPROTO_HTTP1, 5, 8 },
3211  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3212  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3213  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3214  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3215  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3216  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 } };
3217 
3218  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3219  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3220  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3221  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3222  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3223  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3224  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3225  };
3226  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3227  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3228  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3229  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3230  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3231  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3232  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3233  };
3234 
3235  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3236  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3237  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3238  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3239  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3240  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3241  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3242  };
3243  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3244  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3245  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3246  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3247  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3248  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3249  };
3250 
3251  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3252  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3253  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3254  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3255  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3256  };
3257  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3258  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3259  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3260  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3261  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3262  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3263  };
3264 
3265  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3266  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3267  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3268  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3269  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3270  };
3271  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3272  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3273  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3274  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3275  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3276  };
3277 
3278 
3279  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3280  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3281  };
3282  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3283  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3284  };
3285 
3286  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3287  {
3288  80,
3289  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3290  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3291  (1 << ALPROTO_JABBER)),
3292  ((1 << ALPROTO_HTTP1) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3293  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3294  (1 << ALPROTO_SMTP)),
3295  23,
3296  element_ts_80,
3297  element_tc_80,
3298  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3299  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3300  },
3301  {
3302  81,
3303  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3304  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3305  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) |
3306  (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3307  23,
3308  element_ts_81,
3309  element_tc_81,
3310  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3311  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3312  },
3313  { 85,
3314  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) | (1 << ALPROTO_SMTP) |
3315  (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3316  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3317  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3318  23, element_ts_85, element_tc_85,
3319  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3320  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3321  { 90,
3322  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3323  (1 << ALPROTO_JABBER)),
3324  ((1 << ALPROTO_FTP) | (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) |
3325  (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3326  23, element_ts_90, element_tc_90,
3327  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3328  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement) },
3329  { 0,
3330  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) |
3331  (1 << ALPROTO_JABBER)),
3332  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) |
3333  (1 << ALPROTO_SMTP)),
3334  23, element_ts_0, element_tc_0,
3335  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3336  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement) }
3337  };
3338 
3339  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3340  { 85,
3341  (1 << ALPROTO_IMAP),
3342  (1 << ALPROTO_IMAP),
3343  23,
3344  element_ts_85_udp, element_tc_85_udp,
3345  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3346  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3347  },
3348  };
3349 
3351  { IPPROTO_TCP,
3352  ports_tcp,
3353  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3354  },
3355  { IPPROTO_UDP,
3356  ports_udp,
3357  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3358  },
3359  };
3360 
3361 
3362  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3363  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3364  goto end;
3365  }
3366  result = 1;
3367 
3368  end:
3371  return result;
3372 }
3373 
3374 
3375 /** \test test if the engine detect the proto and match with it */
3376 static int AppLayerProtoDetectTest16(void)
3377 {
3378  int result = 0;
3379  Flow *f = NULL;
3380  HtpState *http_state = NULL;
3381  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3382  "User-Agent: Mozilla/1.0\r\n"
3383  "Cookie: hellocatch\r\n\r\n";
3384  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3385  TcpSession ssn;
3386  Packet *p = NULL;
3387  Signature *s = NULL;
3388  ThreadVars tv;
3389  DetectEngineThreadCtx *det_ctx = NULL;
3390  DetectEngineCtx *de_ctx = NULL;
3392 
3393  memset(&tv, 0, sizeof(ThreadVars));
3394  memset(&ssn, 0, sizeof(TcpSession));
3395 
3396  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3397  if (p == NULL) {
3398  printf("packet setup failed: ");
3399  goto end;
3400  }
3401 
3402  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3403  if (f == NULL) {
3404  printf("flow setup failed: ");
3405  goto end;
3406  }
3407  f->protoctx = &ssn;
3408  f->proto = IPPROTO_TCP;
3409  p->flow = f;
3410 
3414 
3415  f->alproto = ALPROTO_HTTP1;
3416 
3417  StreamTcpInitConfig(true);
3418 
3420  if (de_ctx == NULL) {
3421  goto end;
3422  }
3423  de_ctx->flags |= DE_QUIET;
3424 
3425  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3426  "(msg:\"Test content option\"; "
3427  "sid:1;)");
3428  if (s == NULL) {
3429  goto end;
3430  }
3431 
3433  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3434 
3435  FLOWLOCK_WRLOCK(f);
3436  int r = AppLayerParserParse(
3437  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3438  if (r != 0) {
3439  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3440  FLOWLOCK_UNLOCK(f);
3441  goto end;
3442  }
3443  FLOWLOCK_UNLOCK(f);
3444 
3445  http_state = f->alstate;
3446  if (http_state == NULL) {
3447  printf("no http state: ");
3448  goto end;
3449  }
3450 
3451  /* do detect */
3452  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3453 
3454  if (!PacketAlertCheck(p, 1)) {
3455  printf("sig 1 didn't alert, but it should: ");
3456  goto end;
3457  }
3458  result = 1;
3459  end:
3460  if (alp_tctx != NULL)
3462  if (det_ctx != NULL)
3463  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3464  if (de_ctx != NULL)
3466  if (de_ctx != NULL)
3468 
3469  StreamTcpFreeConfig(true);
3470 
3471  UTHFreePackets(&p, 1);
3472  UTHFreeFlow(f);
3473  return result;
3474 }
3475 
3476 /** \test test if the engine detect the proto on a non standar port
3477  * and match with it */
3478 static int AppLayerProtoDetectTest17(void)
3479 {
3480  int result = 0;
3481  Flow *f = NULL;
3482  HtpState *http_state = NULL;
3483  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3484  "User-Agent: Mozilla/1.0\r\n"
3485  "Cookie: hellocatch\r\n\r\n";
3486  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3487  TcpSession ssn;
3488  Packet *p = NULL;
3489  Signature *s = NULL;
3490  ThreadVars tv;
3491  DetectEngineThreadCtx *det_ctx = NULL;
3492  DetectEngineCtx *de_ctx = NULL;
3494 
3495  memset(&tv, 0, sizeof(ThreadVars));
3496  memset(&ssn, 0, sizeof(TcpSession));
3497 
3498  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3499 
3500  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3501  if (f == NULL)
3502  goto end;
3503  f->protoctx = &ssn;
3504  f->proto = IPPROTO_TCP;
3505  p->flow = f;
3509  f->alproto = ALPROTO_HTTP1;
3510 
3511  StreamTcpInitConfig(true);
3512 
3514  if (de_ctx == NULL) {
3515  goto end;
3516  }
3517  de_ctx->flags |= DE_QUIET;
3518 
3519  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3520  "(msg:\"http over non standar port\"; "
3521  "sid:1;)");
3522  if (s == NULL) {
3523  goto end;
3524  }
3525 
3527  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3528 
3529  FLOWLOCK_WRLOCK(f);
3530  int r = AppLayerParserParse(
3531  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3532  if (r != 0) {
3533  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3534  FLOWLOCK_UNLOCK(f);
3535  goto end;
3536  }
3537  FLOWLOCK_UNLOCK(f);
3538 
3539  http_state = f->alstate;
3540  if (http_state == NULL) {
3541  printf("no http state: ");
3542  goto end;
3543  }
3544 
3545  /* do detect */
3546  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3547 
3548  if (!PacketAlertCheck(p, 1)) {
3549  printf("sig 1 didn't alert, but it should: ");
3550  goto end;
3551  }
3552 
3553  result = 1;
3554 
3555  end:
3556  if (alp_tctx != NULL)
3558  if (det_ctx != NULL)
3559  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3560  if (de_ctx != NULL)
3562  if (de_ctx != NULL)
3564 
3565  StreamTcpFreeConfig(true);
3566 
3567  UTHFreePackets(&p, 1);
3568  UTHFreeFlow(f);
3569  return result;
3570 }
3571 
3572 /** \test test if the engine detect the proto and doesn't match
3573  * because the sig expects another proto (ex ftp)*/
3574 static int AppLayerProtoDetectTest18(void)
3575 {
3576  int result = 0;
3577  Flow *f = NULL;
3578  HtpState *http_state = NULL;
3579  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3580  "User-Agent: Mozilla/1.0\r\n"
3581  "Cookie: hellocatch\r\n\r\n";
3582  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3583  TcpSession ssn;
3584  Packet *p = NULL;
3585  Signature *s = NULL;
3586  ThreadVars tv;
3587  DetectEngineThreadCtx *det_ctx = NULL;
3588  DetectEngineCtx *de_ctx = NULL;
3590 
3591  memset(&tv, 0, sizeof(ThreadVars));
3592  memset(&ssn, 0, sizeof(TcpSession));
3593 
3594  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3595 
3596  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3597  if (f == NULL)
3598  goto end;
3599  f->protoctx = &ssn;
3600  f->proto = IPPROTO_TCP;
3601  p->flow = f;
3605  f->alproto = ALPROTO_HTTP1;
3606 
3607  StreamTcpInitConfig(true);
3608 
3610  if (de_ctx == NULL) {
3611  goto end;
3612  }
3613  de_ctx->flags |= DE_QUIET;
3614 
3615  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3616  "(msg:\"Test content option\"; "
3617  "sid:1;)");
3618  if (s == NULL) {
3619  goto end;
3620  }
3621 
3623  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3624 
3625  FLOWLOCK_WRLOCK(f);
3626  int r = AppLayerParserParse(
3627  NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, http_buf1, http_buf1_len);
3628  if (r != 0) {
3629  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3630  FLOWLOCK_UNLOCK(f);
3631  goto end;
3632  }
3633  FLOWLOCK_UNLOCK(f);
3634 
3635  http_state = f->alstate;
3636  if (http_state == NULL) {
3637  printf("no http state: ");
3638  goto end;
3639  }
3640 
3641  /* do detect */
3642  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3643 
3644  if (PacketAlertCheck(p, 1)) {
3645  printf("sig 1 alerted, but it should not (it's not ftp): ");
3646  goto end;
3647  }
3648 
3649  result = 1;
3650  end:
3651  if (alp_tctx != NULL)
3653  if (det_ctx != NULL)
3654  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3655  if (de_ctx != NULL)
3657  if (de_ctx != NULL)
3659 
3660  StreamTcpFreeConfig(true);
3661 
3662  UTHFreePackets(&p, 1);
3663  UTHFreeFlow(f);
3664  return result;
3665 }
3666 
3667 /** \test test if the engine detect the proto and doesn't match
3668  * because the packet has another proto (ex ftp) */
3669 static int AppLayerProtoDetectTest19(void)
3670 {
3671  int result = 0;
3672  Flow *f = NULL;
3673  uint8_t http_buf1[] = "MPUT one\r\n";
3674  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3675  TcpSession ssn;
3676  Packet *p = NULL;
3677  Signature *s = NULL;
3678  ThreadVars tv;
3679  DetectEngineThreadCtx *det_ctx = NULL;
3680  DetectEngineCtx *de_ctx = NULL;
3682 
3683  memset(&tv, 0, sizeof(ThreadVars));
3684  memset(&ssn, 0, sizeof(TcpSession));
3685 
3686  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3687 
3688  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3689  if (f == NULL)
3690  goto end;
3691  f->protoctx = &ssn;
3692  f->proto = IPPROTO_TCP;
3693  p->flow = f;
3697  f->alproto = ALPROTO_FTP;
3698 
3699  StreamTcpInitConfig(true);
3700 
3702  if (de_ctx == NULL) {
3703  goto end;
3704  }
3705  de_ctx->flags |= DE_QUIET;
3706 
3707  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3708  "(msg:\"http over non standar port\"; "
3709  "sid:1;)");
3710  if (s == NULL) {
3711  goto end;
3712  }
3713 
3715  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3716 
3717  FLOWLOCK_WRLOCK(f);
3718  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3719  STREAM_TOSERVER, http_buf1, http_buf1_len);
3720  if (r != 0) {
3721  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3722  FLOWLOCK_UNLOCK(f);
3723  goto end;
3724  }
3725  FLOWLOCK_UNLOCK(f);
3726 
3727  /* do detect */
3728  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3729 
3730  if (PacketAlertCheck(p, 1)) {
3731  printf("sig 1 alerted, but it should not (it's ftp): ");
3732  goto end;
3733  }
3734 
3735  result = 1;
3736 
3737  end:
3738  if (alp_tctx != NULL)
3740  if (det_ctx != NULL)
3741  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3742  if (de_ctx != NULL)
3744  if (de_ctx != NULL)
3746 
3747  StreamTcpFreeConfig(true);
3748  UTHFreePackets(&p, 1);
3749  UTHFreeFlow(f);
3750  return result;
3751 }
3752 
3754 {
3755  SCEnter();
3756 
3757  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3758  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3759  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3760  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3761  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3762  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3763  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3764  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3765  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3766  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3767  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3768  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3769  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3770  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3771  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3772  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3773  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3774  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3775  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3776 
3777  SCReturn;
3778 }
3779 
3780 #endif /* UNITTESTS */
AppLayerProtoDetectPPTestDataPort_
Definition: app-layer-detect-proto.c:2944
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:284
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:2240
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:1152
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:147
FLOW_IS_PE_DONE
#define FLOW_IS_PE_DONE(f, dir)
Definition: flow.h:277
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:279
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:200
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:375
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:449
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:353
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2076
AppLayerProtoDetectUnittestCtxBackup
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
Definition: app-layer-detect-proto.c:2232
AppLayerProtoDetectPPTestDataElement_::alproto_name
const char * alproto_name
Definition: app-layer-detect-proto.c:2936
Flow_::protomap
uint8_t protomap
Definition: flow.h:455
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:758
AppLayerProtoDetectPPTestDataElement
struct AppLayerProtoDetectPPTestDataElement_ AppLayerProtoDetectPPTestDataElement
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:466
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2068
AppLayerProtoDetectSupportedIpprotos
void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
Definition: app-layer-detect-proto.c:2137
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:225
MIN
#define MIN(x, y)
Definition: suricata-common.h:368
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:2940
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:2937
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1653
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:445
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:451
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:2939
util-unittest.h
FlowGetReverseProtoMapping
uint8_t FlowGetReverseProtoMapping(uint8_t rproto)
Definition: flow-util.c:109
HtpState_
Definition: app-layer-htp.h:248
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:280
util-unittest-helper.h
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:270
AppLayerProtoDetectPPTestDataIPProto_
Definition: app-layer-detect-proto.c:2957
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:275
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:485
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:2200
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:437
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:276
DetectEngineThreadCtx_
Definition: detect.h:1003
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:267
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:2950
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:2961
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
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:1999
SCReturn
#define SCReturn
Definition: util-debug.h:302
FLOW_RESET_PM_DONE
#define FLOW_RESET_PM_DONE(f, dir)
Definition: flow.h:283
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:2951
Packet_
Definition: decode.h:414
FLOW_GET_DP
#define FLOW_GET_DP(f)
Definition: flow.h:165
ALPROTO_IMAP
@ ALPROTO_IMAP
Definition: app-layer-protos.h:35
FLOW_GET_SP
#define FLOW_GET_SP(f)
Definition: flow.h:163
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:2213
AppLayerProtoDetectPPTestDataPort_::tc_no_of_element
int tc_no_of_element
Definition: app-layer-detect-proto.c:2953
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:164
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:2947
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:429
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:2945
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:165
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:241
Flow_::alproto_expect
AppProto alproto_expect
Definition: flow.h:469
runmodes.h
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:267
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:1932
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:428
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:451
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:2772
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:2946
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:1211
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:2980
AppLayerProtoDetectAliases_::next
struct AppLayerProtoDetectAliases_ * next
Definition: app-layer-detect-proto.c:169
AppLayerProtoDetectPPTestDataIPProto_::ipproto
uint8_t ipproto
Definition: app-layer-detect-proto.c:2958
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:285
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:625
SWAP_VARS
#define SWAP_VARS(type, a, b)
Definition: suricata-common.h:405
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:764
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:2184
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:3753
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:2941
AppLayerProtoDetectGetCtxThread
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
Definition: app-layer-detect-proto.c:2057
AppLayerProtoDetectGetProtoByName
AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name)
Definition: app-layer-detect-proto.c:2154
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:148
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:461
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:486
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:227
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2023
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:2952
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:2111
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:759
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:149
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
AppLayerProtoDetectConfProtoDetectionEnabledDefault
int AppLayerProtoDetectConfProtoDetectionEnabledDefault(const char *ipproto, const char *alproto, bool default_enabled)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1987
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:462
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:281
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:73
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:460
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:2938
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:250
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:2052
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:2948
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:656
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:1149
AppLayerProtoDetectPPTestDataIPProto_::port
AppLayerProtoDetectPPTestDataPort * port
Definition: app-layer-detect-proto.c:2960
AppLayerProtoDetectGetProtoName
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
Definition: app-layer-detect-proto.c:2179
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:2935