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  ret = -1;
1482  end:
1483  SCReturnInt(ret);
1484 }
1485 
1486 /***** Protocol Retrieval *****/
1487 
1489  Flow *f,
1490  uint8_t *buf, uint32_t buflen,
1491  uint8_t ipproto, uint8_t direction,
1492  bool *reverse_flow)
1493 {
1494  SCEnter();
1495  SCLogDebug("buflen %u for %s direction", buflen,
1496  (direction & STREAM_TOSERVER) ? "toserver" : "toclient");
1497 
1498  AppProto alproto = ALPROTO_UNKNOWN;
1499  AppProto pm_alproto = ALPROTO_UNKNOWN;
1500 
1501  if (!FLOW_IS_PM_DONE(f, direction)) {
1502  AppProto pm_results[ALPROTO_MAX];
1503  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(tctx, f,
1504  buf, buflen, direction, pm_results, reverse_flow);
1505  if (pm_matches > 0) {
1506  alproto = pm_results[0];
1507 
1508  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1509  * to avoid misdetecting DNS as DCERPC. */
1510  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1511  goto end;
1512 
1513  pm_alproto = alproto;
1514 
1515  /* fall through */
1516  }
1517  }
1518 
1519  if (!FLOW_IS_PP_DONE(f, direction)) {
1520  bool rflow = false;
1521  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto,
1522  direction & (STREAM_TOSERVER|STREAM_TOCLIENT), &rflow);
1523  if (AppProtoIsValid(alproto)) {
1524  if (rflow) {
1525  *reverse_flow = true;
1526  }
1527  goto end;
1528  }
1529  }
1530 
1531  /* Look if flow can be found in expectation list */
1532  if (!FLOW_IS_PE_DONE(f, direction)) {
1533  alproto = AppLayerProtoDetectPEGetProto(f, ipproto, direction);
1534  }
1535 
1536  end:
1537  if (!AppProtoIsValid(alproto))
1538  alproto = pm_alproto;
1539 
1540  SCReturnUInt(alproto);
1541 }
1542 
1543 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1544 {
1545  SCEnter();
1546 
1547  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1548 
1549  if (pp == NULL)
1550  goto end;
1551 
1552  while (pp != NULL) {
1553  tmp_pp = pp->next;
1554  AppLayerProtoDetectProbingParserFree(pp);
1555  pp = tmp_pp;
1556  }
1557 
1558  end:
1559  SCReturn;
1560 }
1561 
1562 /***** State Preparation *****/
1563 
1565 {
1566  SCEnter();
1567 
1568  AppLayerProtoDetectPMCtx *ctx_pm;
1569  int i, j;
1570  int ret = 0;
1571 
1572  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1573  for (j = 0; j < 2; j++) {
1574  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1575 
1576  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1577  goto error;
1578 
1579  if (ctx_pm->max_sig_id == 0)
1580  continue;
1581 
1582  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1583  goto error;
1584  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1585  goto error;
1586  }
1587  }
1588 
1589 #ifdef DEBUG
1590  if (SCLogDebugEnabled()) {
1591  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1592  }
1593 #endif
1594 
1595  goto end;
1596  error:
1597  ret = -1;
1598  end:
1599  SCReturnInt(ret);
1600 }
1601 
1602 /***** PP registration *****/
1603 
1604 /** \brief register parser at a port
1605  *
1606  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1607  */
1608 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1609  const char *portstr,
1610  AppProto alproto,
1611  uint16_t min_depth, uint16_t max_depth,
1612  uint8_t direction,
1613  ProbingParserFPtr ProbingParser1,
1614  ProbingParserFPtr ProbingParser2)
1615 {
1616  SCEnter();
1617 
1618  DetectPort *head = NULL;
1619  DetectPortParse(NULL,&head, portstr);
1620  DetectPort *temp_dp = head;
1621  while (temp_dp != NULL) {
1622  uint32_t port = temp_dp->port;
1623  if (port == 0 && temp_dp->port2 != 0)
1624  port++;
1625  for ( ; port <= temp_dp->port2; port++) {
1626  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1627  ipproto,
1628  port,
1629  alproto,
1630  min_depth, max_depth,
1631  direction,
1632  ProbingParser1,
1633  ProbingParser2);
1634  }
1635  temp_dp = temp_dp->next;
1636  }
1637  DetectPortCleanupList(NULL,head);
1638 
1639  SCReturn;
1640 }
1641 
1642 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1643  uint8_t ipproto,
1644  const char *alproto_name,
1645  AppProto alproto,
1646  uint16_t min_depth, uint16_t max_depth,
1649 {
1650  SCEnter();
1651 
1652  char param[100];
1653  int r;
1654  ConfNode *node;
1655  ConfNode *port_node = NULL;
1656  int config = 0;
1657 
1658  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1659  alproto_name, ".detection-ports");
1660  if (r < 0) {
1661  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1662  exit(EXIT_FAILURE);
1663  } else if (r > (int)sizeof(param)) {
1664  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1665  exit(EXIT_FAILURE);
1666  }
1667  node = ConfGetNode(param);
1668  if (node == NULL) {
1669  SCLogDebug("Entry for %s not found.", param);
1670  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1671  alproto_name, ".", ipproto_name, ".detection-ports");
1672  if (r < 0) {
1673  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1674  exit(EXIT_FAILURE);
1675  } else if (r > (int)sizeof(param)) {
1676  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1677  exit(EXIT_FAILURE);
1678  }
1679  node = ConfGetNode(param);
1680  if (node == NULL)
1681  goto end;
1682  }
1683 
1684  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1685  port_node = ConfNodeLookupChild(node, "dp");
1686  if (port_node == NULL)
1687  port_node = ConfNodeLookupChild(node, "toserver");
1688 
1689  if (port_node != NULL && port_node->val != NULL) {
1691  port_node->val,
1692  alproto,
1693  min_depth, max_depth,
1694  STREAM_TOSERVER, /* to indicate dp */
1695  ProbingParserTs, ProbingParserTc);
1696  }
1697 
1698  /* detect by source port of flow */
1699  port_node = ConfNodeLookupChild(node, "sp");
1700  if (port_node == NULL)
1701  port_node = ConfNodeLookupChild(node, "toclient");
1702 
1703  if (port_node != NULL && port_node->val != NULL) {
1705  port_node->val,
1706  alproto,
1707  min_depth, max_depth,
1708  STREAM_TOCLIENT, /* to indicate sp */
1709  ProbingParserTc, ProbingParserTs);
1710 
1711  }
1712 
1713  config = 1;
1714  end:
1715  SCReturnInt(config);
1716 }
1717 
1718 /***** PM registration *****/
1719 
1721  const char *pattern,
1722  uint16_t depth, uint16_t offset,
1723  uint8_t direction)
1724 {
1725  SCEnter();
1726  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1727  pattern, depth, offset,
1728  direction, 1 /* case-sensitive */,
1729  NULL, 0, 0);
1730  SCReturnInt(r);
1731 }
1732 
1734  const char *pattern, uint16_t depth, uint16_t offset,
1735  uint8_t direction,
1736  ProbingParserFPtr PPFunc,
1737  uint16_t pp_min_depth, uint16_t pp_max_depth)
1738 {
1739  SCEnter();
1740  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1741  pattern, depth, offset,
1742  direction, 1 /* case-sensitive */,
1743  PPFunc, pp_min_depth, pp_max_depth);
1744  SCReturnInt(r);
1745 }
1746 
1748  const char *pattern,
1749  uint16_t depth, uint16_t offset,
1750  uint8_t direction)
1751 {
1752  SCEnter();
1753  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1754  pattern, depth, offset,
1755  direction, 0 /* !case-sensitive */,
1756  NULL, 0, 0);
1757  SCReturnInt(r);
1758 }
1759 
1760 /***** Setup/General Registration *****/
1761 
1763 {
1764  SCEnter();
1765 
1766  int i, j;
1767 
1768  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1769 
1770  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1771  uint16_t mpm_matcher = PatternMatchDefaultMatcher();
1772 
1773  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1774  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1775  SCLogError(SC_ERR_FATAL, "Unable to alloc SpmGlobalThreadCtx.");
1776  exit(EXIT_FAILURE);
1777  }
1778 
1779  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1780  for (j = 0; j < 2; j++) {
1781  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1782  }
1783  }
1784 
1786 
1787  SCReturnInt(0);
1788 }
1789 
1790 /**
1791  * \todo incomplete. Need more work.
1792  */
1794 {
1795  SCEnter();
1796 
1797  int ipproto_map = 0;
1798  int dir = 0;
1799  PatIntId id = 0;
1800  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1801  AppLayerProtoDetectPMSignature *sig = NULL;
1802 
1803  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1804  for (dir = 0; dir < 2; dir++) {
1805  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1806  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1807  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1808  sig = pm_ctx->map[id];
1809  AppLayerProtoDetectPMFreeSignature(sig);
1810  }
1811  SCFree(pm_ctx->map);
1812  pm_ctx->map = NULL;
1813  }
1814  }
1815 
1817 
1818  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1819 
1820  SCReturnInt(0);
1821 }
1822 
1823 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1824 {
1825  SCEnter();
1826 
1827  if (alpd_ctx.alproto_names[alproto] == NULL)
1828  alpd_ctx.alproto_names[alproto] = alproto_name;
1829 
1830  SCReturn;
1831 }
1832 
1833 /** \brief request applayer to wrap up this protocol and rerun protocol
1834  * detection.
1835  *
1836  * When this is called, the old session is reset unconditionally. A
1837  * 'detect/log' flush packet is generated for both direction before
1838  * the reset, so allow for final detection and logging.
1839  *
1840  * \param f flow to act on
1841  * \param dp destination port to use in protocol detection. Set to 443
1842  * for start tls, set to the HTTP uri port for CONNECT and
1843  * set to 0 to not use it.
1844  * \param expect_proto expected protocol. AppLayer event will be set if
1845  * detected protocol differs from this.
1846  */
1847 void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1848 {
1850  f->protodetect_dp = dp;
1851  f->alproto_expect = expect_proto;
1852 }
1853 
1854 /** \brief request applayer to wrap up this protocol and rerun protocol
1855  * detection with expectation of TLS. Used by STARTTLS.
1856  *
1857  * Sets detection port to 443 to make port based TLS detection work for
1858  * SMTP, FTP etc as well.
1859  *
1860  * \param f flow to act on
1861  */
1863 {
1865 }
1866 
1868 {
1870  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1872  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1874  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1878 
1880  f->alstate = NULL;
1881  f->alparser = NULL;
1882  f->alproto = ALPROTO_UNKNOWN;
1885 }
1886 
1888  const char *alproto)
1889 {
1890  SCEnter();
1891 
1892  BUG_ON(ipproto == NULL || alproto == NULL);
1893 
1894  int enabled = 1;
1895  char param[100];
1896  ConfNode *node;
1897  int r;
1898 
1899 #ifdef AFLFUZZ_APPLAYER
1900  goto enabled;
1901 #endif
1902  if (RunmodeIsUnittests())
1903  goto enabled;
1904 
1905  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1906  alproto, ".enabled");
1907  if (r < 0) {
1908  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1909  exit(EXIT_FAILURE);
1910  } else if (r > (int)sizeof(param)) {
1911  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1912  exit(EXIT_FAILURE);
1913  }
1914 
1915  node = ConfGetNode(param);
1916  if (node == NULL) {
1917  SCLogDebug("Entry for %s not found.", param);
1918  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1919  alproto, ".", ipproto, ".enabled");
1920  if (r < 0) {
1921  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1922  exit(EXIT_FAILURE);
1923  } else if (r > (int)sizeof(param)) {
1924  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1925  exit(EXIT_FAILURE);
1926  }
1927 
1928  node = ConfGetNode(param);
1929  if (node == NULL) {
1930  SCLogDebug("Entry for %s not found.", param);
1931  goto enabled;
1932  }
1933  }
1934 
1935  if (node->val) {
1936  if (ConfValIsTrue(node->val)) {
1937  goto enabled;
1938  } else if (ConfValIsFalse(node->val)) {
1939  goto disabled;
1940  } else if (strcasecmp(node->val, "detection-only") == 0) {
1941  goto enabled;
1942  }
1943  }
1944 
1945  /* Invalid or null value. */
1946  SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
1947  exit(EXIT_FAILURE);
1948 
1949  disabled:
1950  enabled = 0;
1951  enabled:
1952  SCReturnInt(enabled);
1953 }
1954 
1956 {
1957  SCEnter();
1958 
1959  AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
1960  MpmCtx *mpm_ctx;
1961  MpmThreadCtx *mpm_tctx;
1962  int i, j;
1963  PatIntId max_pat_id = 0;
1964 
1965  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1966  for (j = 0; j < 2; j++) {
1967  if (max_pat_id == 0) {
1968  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1969 
1970  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1971  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1972  {
1973  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1974  }
1975  }
1976  }
1977 
1978  alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
1979  if (alpd_tctx == NULL)
1980  goto error;
1981  memset(alpd_tctx, 0, sizeof(*alpd_tctx));
1982 
1983  /* Get the max pat id for all the mpm ctxs. */
1984  if (PmqSetup(&alpd_tctx->pmq) < 0)
1985  goto error;
1986 
1987  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1988  for (j = 0; j < 2; j++) {
1989  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1990  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1991  mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
1992  }
1993  }
1994 
1995  alpd_tctx->spm_thread_ctx = SpmMakeThreadCtx(alpd_ctx.spm_global_thread_ctx);
1996  if (alpd_tctx->spm_thread_ctx == NULL) {
1997  goto error;
1998  }
1999 
2000  goto end;
2001  error:
2002  if (alpd_tctx != NULL)
2004  alpd_tctx = NULL;
2005  end:
2006  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2007 }
2008 
2010 {
2011  SCEnter();
2012 
2013  MpmCtx *mpm_ctx;
2014  MpmThreadCtx *mpm_tctx;
2015  int ipproto_map, dir;
2016 
2017  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2018  for (dir = 0; dir < 2; dir++) {
2019  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2020  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2021  mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2022  }
2023  }
2024  PmqFree(&alpd_tctx->pmq);
2025  if (alpd_tctx->spm_thread_ctx != NULL) {
2026  SpmDestroyThreadCtx(alpd_tctx->spm_thread_ctx);
2027  }
2028  SCFree(alpd_tctx);
2029 
2030  SCReturn;
2031 }
2032 
2033 /***** Utility *****/
2034 
2035 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2036 {
2037  SCEnter();
2038 
2039  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2040  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2041  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2042 
2043  SCReturn;
2044 }
2045 
2047 {
2048  SCEnter();
2049 
2050  AppProto a;
2051  for (a = 0; a < ALPROTO_MAX; a++) {
2052  if (alpd_ctx.alproto_names[a] != NULL &&
2053  strlen(alpd_ctx.alproto_names[a]) == strlen(alproto_name) &&
2054  (SCMemcmp(alpd_ctx.alproto_names[a], alproto_name, strlen(alproto_name)) == 0))
2055  {
2056  SCReturnCT(a, "AppProto");
2057  }
2058  }
2059 
2060  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2061 }
2062 
2064 {
2065  return alpd_ctx.alproto_names[alproto];
2066 }
2067 
2069 {
2070  SCEnter();
2071 
2072  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2073 
2074  int alproto;
2075 
2076  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2077  if (alpd_ctx.alproto_names[alproto] != NULL)
2078  alprotos[alproto] = 1;
2079  }
2080 
2081  SCReturn;
2082 }
2083 
2085 
2086 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2087  uint8_t *ipprotos)
2088 {
2089  if (expectation_proto[alproto] == IPPROTO_TCP) {
2090  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2091  }
2092  if (expectation_proto[alproto] == IPPROTO_UDP) {
2093  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2094  }
2095 }
2096 
2097 void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
2098 {
2099  if (expectation_proto[alproto]) {
2100  if (proto != expectation_proto[alproto]) {
2102  "Expectation on 2 IP protocols are not supported");
2103  }
2104  }
2105  expectation_proto[alproto] = proto;
2106 }
2107 
2108 /***** Unittests *****/
2109 
2110 #ifdef UNITTESTS
2111 
2112 #include "app-layer-htp.h"
2113 
2114 static AppLayerProtoDetectCtx alpd_ctx_ut;
2115 
2117 {
2118  SCEnter();
2119  alpd_ctx_ut = alpd_ctx;
2120  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2121  SCReturn;
2122 }
2123 
2125 {
2126  SCEnter();
2127  alpd_ctx = alpd_ctx_ut;
2128  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2129  SCReturn;
2130 }
2131 
2132 static int AppLayerProtoDetectTest01(void)
2133 {
2136 
2137  const char *buf = "HTTP";
2139  buf = "GET";
2140  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOSERVER);
2141 
2143  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2144  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2145 
2148  PASS;
2149 }
2150 
2151 static int AppLayerProtoDetectTest02(void)
2152 {
2155 
2156  const char *buf = "HTTP";
2158  buf = "ftp";
2160 
2162  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2163  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2164 
2165  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2166  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2167 
2170 
2173  PASS;
2174 }
2175 
2176 static int AppLayerProtoDetectTest03(void)
2177 {
2180 
2181  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2182  AppProto pm_results[ALPROTO_MAX];
2183  memset(pm_results, 0, sizeof(pm_results));
2184  Flow f;
2185  memset(&f, 0x00, sizeof(f));
2186  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2187 
2188 
2189  const char *buf = "HTTP";
2191  buf = "220 ";
2193 
2195  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2196  * it sets internal structures which depends on the above function. */
2198  FAIL_IF_NULL(alpd_tctx);
2199 
2200  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2201  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2202  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2203  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2206 
2207  bool rflow = false;
2208  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2209  &f, l7data, sizeof(l7data),
2211  pm_results, &rflow);
2212  FAIL_IF(cnt != 1);
2213  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2214 
2218  PASS;
2219 }
2220 
2221 static int AppLayerProtoDetectTest04(void)
2222 {
2225 
2226  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2227  Flow f;
2228  memset(&f, 0x00, sizeof(f));
2229  AppProto pm_results[ALPROTO_MAX];
2230  memset(pm_results, 0, sizeof(pm_results));
2231  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2232 
2233  const char *buf = "200 ";
2235 
2237  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2238  * it sets internal structures which depends on the above function. */
2240  FAIL_IF_NULL(alpd_tctx);
2241 
2242  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2243  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2244  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2245  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2247 
2248  bool rdir = false;
2249  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2250  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2251  pm_results, &rdir);
2252  FAIL_IF(cnt != 1);
2253  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2254 
2258  PASS;
2259 }
2260 
2261 static int AppLayerProtoDetectTest05(void)
2262 {
2265 
2266  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2267  AppProto pm_results[ALPROTO_MAX];
2268  memset(pm_results, 0, sizeof(pm_results));
2269  Flow f;
2270  memset(&f, 0x00, sizeof(f));
2271  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2272 
2273  const char *buf = "HTTP";
2275  buf = "220 ";
2277 
2279  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2280  * it sets internal structures which depends on the above function. */
2282  FAIL_IF_NULL(alpd_tctx);
2283 
2284  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2285  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2286  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2287  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2290 
2291  bool rdir = false;
2292  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2293  &f, l7data, sizeof(l7data),
2295  pm_results, &rdir);
2296  FAIL_IF(cnt != 1);
2297  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2298 
2302  PASS;
2303 }
2304 
2305 static int AppLayerProtoDetectTest06(void)
2306 {
2309 
2310  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2311  AppProto pm_results[ALPROTO_MAX];
2312  memset(pm_results, 0, sizeof(pm_results));
2313  Flow f;
2314  memset(&f, 0x00, sizeof(f));
2315  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2316 
2317  const char *buf = "HTTP";
2319  buf = "220 ";
2321 
2323  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2324  * it sets internal structures which depends on the above function. */
2326  FAIL_IF_NULL(alpd_tctx);
2327 
2328  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2329  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2330  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2331  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2334 
2335  bool rdir = false;
2336  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2337  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2338  pm_results, &rdir);
2339  FAIL_IF(cnt != 1);
2340  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2341 
2345  PASS;
2346 }
2347 
2348 static int AppLayerProtoDetectTest07(void)
2349 {
2352 
2353  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2354  Flow f;
2355  memset(&f, 0x00, sizeof(f));
2356  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2357  AppProto pm_results[ALPROTO_MAX];
2358  memset(pm_results, 0, sizeof(pm_results));
2359 
2360  const char *buf = "HTTP";
2362 
2364  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2365  * it sets internal structures which depends on the above function. */
2367 
2368  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2369  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2370  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2371  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2373 
2374  bool rdir = false;
2375  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2376  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2377  pm_results, &rdir);
2378  FAIL_IF(cnt != 0);
2379 
2383  PASS;
2384 }
2385 
2386 static int AppLayerProtoDetectTest08(void)
2387 {
2390 
2391  uint8_t l7data[] = {
2392  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2393  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2394  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2395  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2396  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2397  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2398  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2399  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2400  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2401  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2402  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2403  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2404  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2405  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2406  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2407  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2408  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2409  0x00
2410  };
2411  AppProto pm_results[ALPROTO_MAX];
2412  memset(pm_results, 0, sizeof(pm_results));
2413  Flow f;
2414  memset(&f, 0x00, sizeof(f));
2415  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2416 
2417  const char *buf = "|ff|SMB";
2419 
2421  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2422  * it sets internal structures which depends on the above function. */
2424  FAIL_IF_NULL(alpd_tctx);
2425 
2426  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2427  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2428  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2429  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2431 
2432  bool rdir = false;
2433  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2434  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2435  pm_results, &rdir);
2436  FAIL_IF(cnt != 1);
2437  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2438 
2442  PASS;
2443 }
2444 
2445 static int AppLayerProtoDetectTest09(void)
2446 {
2449 
2450  uint8_t l7data[] = {
2451  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2452  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2453  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2454  0x00, 0x00, 0x00, 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, 0x24, 0x00, 0x01, 0x00,
2460  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 0x02
2465  };
2466  AppProto pm_results[ALPROTO_MAX];
2467  memset(pm_results, 0, sizeof(pm_results));
2468  Flow f;
2469  memset(&f, 0x00, sizeof(f));
2470  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2471 
2472  const char *buf = "|fe|SMB";
2474 
2476  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2477  * it sets internal structures which depends on the above function. */
2479  FAIL_IF_NULL(alpd_tctx);
2480 
2481  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2482  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2483  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2484  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2486 
2487  bool rdir = false;
2488  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2489  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2490  pm_results, &rdir);
2491  FAIL_IF(cnt != 1);
2492  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2493 
2497  PASS;
2498 }
2499 
2500 static int AppLayerProtoDetectTest10(void)
2501 {
2504 
2505  uint8_t l7data[] = {
2506  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2507  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2508  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2509  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2510  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2511  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2512  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2513  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2514  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2515  };
2516  AppProto pm_results[ALPROTO_MAX];
2517  memset(pm_results, 0, sizeof(pm_results));
2518  Flow f;
2519  memset(&f, 0x00, sizeof(f));
2520  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2521 
2522  const char *buf = "|05 00|";
2524 
2526  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2527  * it sets internal structures which depends on the above function. */
2529  FAIL_IF_NULL(alpd_tctx);
2530 
2531  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2532  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2533  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2534  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2536 
2537  bool rdir = false;
2538  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2539  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2540  pm_results, &rdir);
2541  FAIL_IF(cnt != 1);
2542  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2543 
2547  PASS;
2548 }
2549 
2550 /**
2551  * \test Why we still get http for connect... obviously because
2552  * we also match on the reply, duh
2553  */
2554 static int AppLayerProtoDetectTest11(void)
2555 {
2558 
2559  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2560  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2561  AppProto pm_results[ALPROTO_MAX];
2562  memset(pm_results, 0, sizeof(pm_results));
2563  Flow f;
2564  memset(&f, 0x00, sizeof(f));
2565  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2566 
2567  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2568  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2569  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2570  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2571  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2572  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2573  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2575 
2577  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2578  * it sets internal structures which depends on the above function. */
2580  FAIL_IF_NULL(alpd_tctx);
2581 
2582  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2583  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2584  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2585  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2586 
2595 
2596  bool rdir = false;
2597  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2598  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2599  pm_results, &rdir);
2600  FAIL_IF(cnt != 1);
2601  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2602 
2603  memset(pm_results, 0, sizeof(pm_results));
2604  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2605  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2606  pm_results, &rdir);
2607  FAIL_IF(cnt != 1);
2608  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2609 
2613  PASS;
2614 }
2615 
2616 /**
2617  * \test AlpProtoSignature test
2618  */
2619 static int AppLayerProtoDetectTest12(void)
2620 {
2623 
2624  int r = 0;
2625 
2626  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2627  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2628  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2629  {
2630  printf("failure 1\n");
2631  goto end;
2632  }
2633 
2635  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2636  printf("failure 2\n");
2637  goto end;
2638  }
2639  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2640  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2641  {
2642  printf("failure 3\n");
2643  goto end;
2644  }
2645  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
2646  printf("failure 4\n");
2647  goto end;
2648  }
2649  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2650  printf("failure 5\n");
2651  goto end;
2652  }
2653  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2654  printf("failure 6\n");
2655  goto end;
2656  }
2657 
2658  r = 1;
2659 
2660  end:
2663  return r;
2664 }
2665 
2666 /**
2667  * \test What about if we add some sigs only for udp but call for tcp?
2668  * It should not detect any proto
2669  */
2670 static int AppLayerProtoDetectTest13(void)
2671 {
2674 
2675  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2676  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2677  AppProto pm_results[ALPROTO_MAX];
2678 
2679  Flow f;
2680  memset(&f, 0x00, sizeof(f));
2681  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2682 
2683  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2684  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2685  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2686  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2687  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2688  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2689  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2691 
2693  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2694  * it sets internal structures which depends on the above function. */
2696 
2697  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2698  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2699 
2708 
2709  memset(pm_results, 0, sizeof(pm_results));
2710  bool rdir = false;
2711  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2712  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2713  pm_results, &rdir);
2714  FAIL_IF(cnt != 0);
2715 
2716  memset(pm_results, 0, sizeof(pm_results));
2717  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2718  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2719  pm_results, &rdir);
2720  FAIL_IF(cnt != 0);
2721 
2725  PASS;
2726 }
2727 
2728 /**
2729  * \test What about if we add some sigs only for udp calling it for UDP?
2730  * It should detect ALPROTO_HTTP (over udp). This is just a check
2731  * to ensure that TCP/UDP differences work correctly.
2732  */
2733 static int AppLayerProtoDetectTest14(void)
2734 {
2737 
2738  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2739  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2740  AppProto pm_results[ALPROTO_MAX];
2741  uint32_t cnt;
2742  Flow f;
2743  memset(&f, 0x00, sizeof(f));
2744  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2745 
2746  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2747  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2748  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2749  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2750  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2751  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2752  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2754 
2756  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2757  * it sets internal structures which depends on the above function. */
2759  FAIL_IF_NULL(alpd_tctx);
2760 
2761  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2762  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2763 
2772 
2773  memset(pm_results, 0, sizeof(pm_results));
2774  bool rdir = false;
2775  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2776  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2777  pm_results, &rdir);
2778  FAIL_IF(cnt != 1);
2779  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2780 
2781  memset(pm_results, 0, sizeof(pm_results));
2782  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2783  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2784  pm_results, &rdir);
2785  FAIL_IF(cnt != 1);
2786  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2787 
2791  PASS;
2792 }
2793 
2795  const char *alproto_name;
2797  uint16_t port;
2798  uint32_t alproto_mask;
2799  uint32_t min_depth;
2800  uint32_t max_depth;
2802 
2804  uint16_t port;
2805  uint32_t alproto_mask;
2806  uint16_t dp_max_depth;
2807  uint16_t sp_max_depth;
2808 
2814 
2815 
2817  uint8_t ipproto;
2818 
2822 
2823 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2825  int no_of_ip_proto)
2826 {
2827  int result = 0;
2828  int i = -1, j = -1 , k = -1;
2829 #ifdef DEBUG
2830  int dir = 0;
2831 #endif
2832  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2833  if (pp->ipproto != ip_proto[i].ipproto)
2834  goto end;
2835 
2837  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2838  if (pp_port->port != ip_proto[i].port[k].port)
2839  goto end;
2840  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2841  goto end;
2842  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2843  goto end;
2844  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2845  goto end;
2846  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2847  goto end;
2848 
2849  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2850 #ifdef DEBUG
2851  dir = 0;
2852 #endif
2853  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2854  j++, pp_element = pp_element->next) {
2855 
2856  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2857  goto end;
2858  }
2859  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
2860  goto end;
2861  }
2862  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2863  goto end;
2864  }
2865  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2866  goto end;
2867  }
2868  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2869  goto end;
2870  }
2871  } /* for */
2872  if (pp_element != NULL)
2873  goto end;
2874 
2875  pp_element = pp_port->sp;
2876 #ifdef DEBUG
2877  dir = 1;
2878 #endif
2879  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2880  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2881  goto end;
2882  }
2883  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
2884  goto end;
2885  }
2886  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2887  goto end;
2888  }
2889  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2890  goto end;
2891  }
2892  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2893  goto end;
2894  }
2895  } /* for */
2896  if (pp_element != NULL)
2897  goto end;
2898  }
2899  if (pp_port != NULL)
2900  goto end;
2901  }
2902  if (pp != NULL)
2903  goto end;
2904 
2905  result = 1;
2906  end:
2907 #ifdef DEBUG
2908  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2909 #endif
2910  return result;
2911 }
2912 
2913 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2914  uint8_t *input,
2915  uint32_t input_len, uint8_t *rdir)
2916 {
2917  return 0;
2918 }
2919 
2920 static int AppLayerProtoDetectTest15(void)
2921 {
2924 
2925  int result = 0;
2926 
2927  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2928  "80",
2929  ALPROTO_HTTP,
2930  5, 8,
2931  STREAM_TOSERVER,
2932  ProbingParserDummyForTesting, NULL);
2933  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2934  "80",
2935  ALPROTO_SMB,
2936  5, 6,
2937  STREAM_TOSERVER,
2938  ProbingParserDummyForTesting, NULL);
2939  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2940  "80",
2941  ALPROTO_FTP,
2942  7, 10,
2943  STREAM_TOSERVER,
2944  ProbingParserDummyForTesting, NULL);
2945 
2946  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2947  "81",
2949  9, 10,
2950  STREAM_TOSERVER,
2951  ProbingParserDummyForTesting, NULL);
2952  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2953  "81",
2954  ALPROTO_FTP,
2955  7, 15,
2956  STREAM_TOSERVER,
2957  ProbingParserDummyForTesting, NULL);
2958  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2959  "0",
2960  ALPROTO_SMTP,
2961  12, 0,
2962  STREAM_TOSERVER,
2963  ProbingParserDummyForTesting, NULL);
2964  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2965  "0",
2966  ALPROTO_TLS,
2967  12, 18,
2968  STREAM_TOSERVER,
2969  ProbingParserDummyForTesting, NULL);
2970 
2971  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2972  "85",
2974  9, 10,
2975  STREAM_TOSERVER,
2976  ProbingParserDummyForTesting, NULL);
2977  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2978  "85",
2979  ALPROTO_FTP,
2980  7, 15,
2981  STREAM_TOSERVER,
2982  ProbingParserDummyForTesting, NULL);
2983  result = 1;
2984 
2985  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
2986  "85",
2987  ALPROTO_IMAP,
2988  12, 23,
2989  STREAM_TOSERVER,
2990  ProbingParserDummyForTesting, NULL);
2991 
2992  /* toclient */
2993  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2994  "0",
2996  12, 23,
2998  ProbingParserDummyForTesting, NULL);
2999  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3000  "0",
3001  ALPROTO_IRC,
3002  12, 14,
3004  ProbingParserDummyForTesting, NULL);
3005 
3006  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3007  "85",
3009  9, 10,
3011  ProbingParserDummyForTesting, NULL);
3012  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3013  "81",
3014  ALPROTO_FTP,
3015  7, 15,
3017  ProbingParserDummyForTesting, NULL);
3018  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3019  "0",
3020  ALPROTO_TLS,
3021  12, 18,
3023  ProbingParserDummyForTesting, NULL);
3024  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3025  "80",
3026  ALPROTO_HTTP,
3027  5, 8,
3029  ProbingParserDummyForTesting, NULL);
3030  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3031  "81",
3033  9, 10,
3035  ProbingParserDummyForTesting, NULL);
3036  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3037  "90",
3038  ALPROTO_FTP,
3039  7, 15,
3041  ProbingParserDummyForTesting, NULL);
3042  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3043  "80",
3044  ALPROTO_SMB,
3045  5, 6,
3047  ProbingParserDummyForTesting, NULL);
3048  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3049  "85",
3050  ALPROTO_IMAP,
3051  12, 23,
3053  ProbingParserDummyForTesting, NULL);
3054  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3055  "0",
3056  ALPROTO_SMTP,
3057  12, 17,
3059  ProbingParserDummyForTesting, NULL);
3060  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3061  "80",
3062  ALPROTO_FTP,
3063  7, 10,
3065  ProbingParserDummyForTesting, NULL);
3066 
3067  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3068  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3069  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3070  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3071  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3072  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3073  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3074  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3075  };
3076  AppLayerProtoDetectPPTestDataElement element_tc_80[] = {
3077  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3078  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3079  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3080  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3081  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3082  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3083  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3084  };
3085 
3086  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3087  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3088  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3089  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3090  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3091  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3092  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3093  };
3094  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3095  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3096  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3097  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3098  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3099  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3100  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3101  };
3102 
3103  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3104  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3105  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3106  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3107  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3108  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3109  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3110  };
3111  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3112  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3113  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3114  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3115  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3116  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3117  };
3118 
3119  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3120  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3121  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3122  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3123  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3124  };
3125  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3126  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3127  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3128  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3129  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3130  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3131  };
3132 
3133  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3134  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3135  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3136  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3137  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3138  };
3139  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3140  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3141  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3142  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3143  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3144  };
3145 
3146 
3147  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3148  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3149  };
3150  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3151  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3152  };
3153 
3154  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3155  { 80,
3156  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3157  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3158  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3159  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3160  23,
3161  element_ts_80, element_tc_80,
3162  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3163  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3164  },
3165  { 81,
3166  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3167  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3168  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) |
3169  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3170  23,
3171  element_ts_81, element_tc_81,
3172  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3173  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3174  },
3175  { 85,
3176  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3177  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3178  ((1 << ALPROTO_DCERPC) |
3179  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3180  23,
3181  element_ts_85, element_tc_85,
3182  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3183  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement)
3184  },
3185  { 90,
3186  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3187  ((1 << ALPROTO_FTP) |
3188  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3189  23,
3190  element_ts_90, element_tc_90,
3191  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3192  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement)
3193  },
3194  { 0,
3195  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3196  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3197  23,
3198  element_ts_0, element_tc_0,
3199  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3200  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement)
3201  }
3202  };
3203 
3204  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3205  { 85,
3206  (1 << ALPROTO_IMAP),
3207  (1 << ALPROTO_IMAP),
3208  23,
3209  element_ts_85_udp, element_tc_85_udp,
3210  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3211  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3212  },
3213  };
3214 
3216  { IPPROTO_TCP,
3217  ports_tcp,
3218  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3219  },
3220  { IPPROTO_UDP,
3221  ports_udp,
3222  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3223  },
3224  };
3225 
3226 
3227  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3228  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3229  goto end;
3230  }
3231  result = 1;
3232 
3233  end:
3236  return result;
3237 }
3238 
3239 
3240 /** \test test if the engine detect the proto and match with it */
3241 static int AppLayerProtoDetectTest16(void)
3242 {
3243  int result = 0;
3244  Flow *f = NULL;
3245  HtpState *http_state = NULL;
3246  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3247  "User-Agent: Mozilla/1.0\r\n"
3248  "Cookie: hellocatch\r\n\r\n";
3249  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3250  TcpSession ssn;
3251  Packet *p = NULL;
3252  Signature *s = NULL;
3253  ThreadVars tv;
3254  DetectEngineThreadCtx *det_ctx = NULL;
3255  DetectEngineCtx *de_ctx = NULL;
3257 
3258  memset(&tv, 0, sizeof(ThreadVars));
3259  memset(&ssn, 0, sizeof(TcpSession));
3260 
3261  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3262  if (p == NULL) {
3263  printf("packet setup failed: ");
3264  goto end;
3265  }
3266 
3267  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3268  if (f == NULL) {
3269  printf("flow setup failed: ");
3270  goto end;
3271  }
3272  f->protoctx = &ssn;
3273  f->proto = IPPROTO_TCP;
3274  p->flow = f;
3275 
3279 
3280  f->alproto = ALPROTO_HTTP;
3281 
3283 
3284  de_ctx = DetectEngineCtxInit();
3285  if (de_ctx == NULL) {
3286  goto end;
3287  }
3288  de_ctx->flags |= DE_QUIET;
3289 
3290  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3291  "(msg:\"Test content option\"; "
3292  "sid:1;)");
3293  if (s == NULL) {
3294  goto end;
3295  }
3296 
3297  SigGroupBuild(de_ctx);
3298  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3299 
3300  FLOWLOCK_WRLOCK(f);
3301  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3302  STREAM_TOSERVER, http_buf1, http_buf1_len);
3303  if (r != 0) {
3304  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3305  FLOWLOCK_UNLOCK(f);
3306  goto end;
3307  }
3308  FLOWLOCK_UNLOCK(f);
3309 
3310  http_state = f->alstate;
3311  if (http_state == NULL) {
3312  printf("no http state: ");
3313  goto end;
3314  }
3315 
3316  /* do detect */
3317  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3318 
3319  if (!PacketAlertCheck(p, 1)) {
3320  printf("sig 1 didn't alert, but it should: ");
3321  goto end;
3322  }
3323  result = 1;
3324  end:
3325  if (alp_tctx != NULL)
3326  AppLayerParserThreadCtxFree(alp_tctx);
3327  if (det_ctx != NULL)
3328  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3329  if (de_ctx != NULL)
3330  SigGroupCleanup(de_ctx);
3331  if (de_ctx != NULL)
3332  DetectEngineCtxFree(de_ctx);
3333 
3335 
3336  UTHFreePackets(&p, 1);
3337  UTHFreeFlow(f);
3338  return result;
3339 }
3340 
3341 /** \test test if the engine detect the proto on a non standar port
3342  * and match with it */
3343 static int AppLayerProtoDetectTest17(void)
3344 {
3345  int result = 0;
3346  Flow *f = NULL;
3347  HtpState *http_state = NULL;
3348  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3349  "User-Agent: Mozilla/1.0\r\n"
3350  "Cookie: hellocatch\r\n\r\n";
3351  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3352  TcpSession ssn;
3353  Packet *p = NULL;
3354  Signature *s = NULL;
3355  ThreadVars tv;
3356  DetectEngineThreadCtx *det_ctx = NULL;
3357  DetectEngineCtx *de_ctx = NULL;
3359 
3360  memset(&tv, 0, sizeof(ThreadVars));
3361  memset(&ssn, 0, sizeof(TcpSession));
3362 
3363  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3364 
3365  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3366  if (f == NULL)
3367  goto end;
3368  f->protoctx = &ssn;
3369  f->proto = IPPROTO_TCP;
3370  p->flow = f;
3374  f->alproto = ALPROTO_HTTP;
3375 
3377 
3378  de_ctx = DetectEngineCtxInit();
3379  if (de_ctx == NULL) {
3380  goto end;
3381  }
3382  de_ctx->flags |= DE_QUIET;
3383 
3384  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3385  "(msg:\"http over non standar port\"; "
3386  "sid:1;)");
3387  if (s == NULL) {
3388  goto end;
3389  }
3390 
3391  SigGroupBuild(de_ctx);
3392  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3393 
3394  FLOWLOCK_WRLOCK(f);
3395  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3396  STREAM_TOSERVER, http_buf1, http_buf1_len);
3397  if (r != 0) {
3398  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3399  FLOWLOCK_UNLOCK(f);
3400  goto end;
3401  }
3402  FLOWLOCK_UNLOCK(f);
3403 
3404  http_state = f->alstate;
3405  if (http_state == NULL) {
3406  printf("no http state: ");
3407  goto end;
3408  }
3409 
3410  /* do detect */
3411  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3412 
3413  if (!PacketAlertCheck(p, 1)) {
3414  printf("sig 1 didn't alert, but it should: ");
3415  goto end;
3416  }
3417 
3418  result = 1;
3419 
3420  end:
3421  if (alp_tctx != NULL)
3422  AppLayerParserThreadCtxFree(alp_tctx);
3423  if (det_ctx != NULL)
3424  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3425  if (de_ctx != NULL)
3426  SigGroupCleanup(de_ctx);
3427  if (de_ctx != NULL)
3428  DetectEngineCtxFree(de_ctx);
3429 
3431 
3432  UTHFreePackets(&p, 1);
3433  UTHFreeFlow(f);
3434  return result;
3435 }
3436 
3437 /** \test test if the engine detect the proto and doesn't match
3438  * because the sig expects another proto (ex ftp)*/
3439 static int AppLayerProtoDetectTest18(void)
3440 {
3441  int result = 0;
3442  Flow *f = NULL;
3443  HtpState *http_state = NULL;
3444  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3445  "User-Agent: Mozilla/1.0\r\n"
3446  "Cookie: hellocatch\r\n\r\n";
3447  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3448  TcpSession ssn;
3449  Packet *p = NULL;
3450  Signature *s = NULL;
3451  ThreadVars tv;
3452  DetectEngineThreadCtx *det_ctx = NULL;
3453  DetectEngineCtx *de_ctx = NULL;
3455 
3456  memset(&tv, 0, sizeof(ThreadVars));
3457  memset(&ssn, 0, sizeof(TcpSession));
3458 
3459  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3460 
3461  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3462  if (f == NULL)
3463  goto end;
3464  f->protoctx = &ssn;
3465  f->proto = IPPROTO_TCP;
3466  p->flow = f;
3470  f->alproto = ALPROTO_HTTP;
3471 
3473 
3474  de_ctx = DetectEngineCtxInit();
3475  if (de_ctx == NULL) {
3476  goto end;
3477  }
3478  de_ctx->flags |= DE_QUIET;
3479 
3480  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3481  "(msg:\"Test content option\"; "
3482  "sid:1;)");
3483  if (s == NULL) {
3484  goto end;
3485  }
3486 
3487  SigGroupBuild(de_ctx);
3488  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3489 
3490  FLOWLOCK_WRLOCK(f);
3491  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3492  STREAM_TOSERVER, http_buf1, http_buf1_len);
3493  if (r != 0) {
3494  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3495  FLOWLOCK_UNLOCK(f);
3496  goto end;
3497  }
3498  FLOWLOCK_UNLOCK(f);
3499 
3500  http_state = f->alstate;
3501  if (http_state == NULL) {
3502  printf("no http state: ");
3503  goto end;
3504  }
3505 
3506  /* do detect */
3507  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3508 
3509  if (PacketAlertCheck(p, 1)) {
3510  printf("sig 1 alerted, but it should not (it's not ftp): ");
3511  goto end;
3512  }
3513 
3514  result = 1;
3515  end:
3516  if (alp_tctx != NULL)
3517  AppLayerParserThreadCtxFree(alp_tctx);
3518  if (det_ctx != NULL)
3519  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3520  if (de_ctx != NULL)
3521  SigGroupCleanup(de_ctx);
3522  if (de_ctx != NULL)
3523  DetectEngineCtxFree(de_ctx);
3524 
3526 
3527  UTHFreePackets(&p, 1);
3528  UTHFreeFlow(f);
3529  return result;
3530 }
3531 
3532 /** \test test if the engine detect the proto and doesn't match
3533  * because the packet has another proto (ex ftp) */
3534 static int AppLayerProtoDetectTest19(void)
3535 {
3536  int result = 0;
3537  Flow *f = NULL;
3538  uint8_t http_buf1[] = "MPUT one\r\n";
3539  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3540  TcpSession ssn;
3541  Packet *p = NULL;
3542  Signature *s = NULL;
3543  ThreadVars tv;
3544  DetectEngineThreadCtx *det_ctx = NULL;
3545  DetectEngineCtx *de_ctx = NULL;
3547 
3548  memset(&tv, 0, sizeof(ThreadVars));
3549  memset(&ssn, 0, sizeof(TcpSession));
3550 
3551  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3552 
3553  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3554  if (f == NULL)
3555  goto end;
3556  f->protoctx = &ssn;
3557  f->proto = IPPROTO_TCP;
3558  p->flow = f;
3562  f->alproto = ALPROTO_FTP;
3563 
3565 
3566  de_ctx = DetectEngineCtxInit();
3567  if (de_ctx == NULL) {
3568  goto end;
3569  }
3570  de_ctx->flags |= DE_QUIET;
3571 
3572  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3573  "(msg:\"http over non standar port\"; "
3574  "sid:1;)");
3575  if (s == NULL) {
3576  goto end;
3577  }
3578 
3579  SigGroupBuild(de_ctx);
3580  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3581 
3582  FLOWLOCK_WRLOCK(f);
3583  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3584  STREAM_TOSERVER, http_buf1, http_buf1_len);
3585  if (r != 0) {
3586  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3587  FLOWLOCK_UNLOCK(f);
3588  goto end;
3589  }
3590  FLOWLOCK_UNLOCK(f);
3591 
3592  /* do detect */
3593  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3594 
3595  if (PacketAlertCheck(p, 1)) {
3596  printf("sig 1 alerted, but it should not (it's ftp): ");
3597  goto end;
3598  }
3599 
3600  result = 1;
3601 
3602  end:
3603  if (alp_tctx != NULL)
3604  AppLayerParserThreadCtxFree(alp_tctx);
3605  if (det_ctx != NULL)
3606  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3607  if (de_ctx != NULL)
3608  SigGroupCleanup(de_ctx);
3609  if (de_ctx != NULL)
3610  DetectEngineCtxFree(de_ctx);
3611 
3613  UTHFreePackets(&p, 1);
3614  UTHFreeFlow(f);
3615  return result;
3616 }
3617 
3619 {
3620  SCEnter();
3621 
3622  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3623  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3624  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3625  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3626  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3627  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3628  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3629  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3630  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3631  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3632  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3633  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3634  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3635  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3636  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3637  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3638  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3639  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3640  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3641 
3642  SCReturn;
3643 }
3644 
3645 #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:443
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:730
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:496
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:724
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:296
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:197
#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:725
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:1742
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:437
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:261
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:166
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:228
#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:197
#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:210
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:1092
#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:441
uint16_t port2
Definition: detect.h:198
#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:1090
Port structure for detection engine.
Definition: detect.h:196
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