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