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_TEMPLATE_RUST)
869  printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
870  else if (pp_pe->alproto == ALPROTO_TEMPLATE)
871  printf(" alproto: ALPROTO_TEMPLATE\n");
872  else if (pp_pe->alproto == ALPROTO_DNP3)
873  printf(" alproto: ALPROTO_DNP3\n");
874  else
875  printf("impossible\n");
876 
877  printf(" port: %"PRIu16 "\n", pp_pe->port);
878  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
879  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
880  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
881 
882  printf("\n");
883  }
884  }
885 
886  if (pp_port->sp == NULL) {
887  continue;
888  }
889 
890  printf(" Source port: (max-depth: %"PRIu16 ", "
891  "mask - %"PRIu32")\n",
892  pp_port->sp_max_depth,
893  pp_port->alproto_mask);
894  pp_pe = pp_port->sp;
895  for ( ; pp_pe != NULL; pp_pe = pp_pe->next) {
896 
897  if (pp_pe->alproto == ALPROTO_HTTP)
898  printf(" alproto: ALPROTO_HTTP\n");
899  else if (pp_pe->alproto == ALPROTO_FTP)
900  printf(" alproto: ALPROTO_FTP\n");
901  else if (pp_pe->alproto == ALPROTO_FTPDATA)
902  printf(" alproto: ALPROTO_FTPDATA\n");
903  else if (pp_pe->alproto == ALPROTO_SMTP)
904  printf(" alproto: ALPROTO_SMTP\n");
905  else if (pp_pe->alproto == ALPROTO_TLS)
906  printf(" alproto: ALPROTO_TLS\n");
907  else if (pp_pe->alproto == ALPROTO_SSH)
908  printf(" alproto: ALPROTO_SSH\n");
909  else if (pp_pe->alproto == ALPROTO_IMAP)
910  printf(" alproto: ALPROTO_IMAP\n");
911  else if (pp_pe->alproto == ALPROTO_MSN)
912  printf(" alproto: ALPROTO_MSN\n");
913  else if (pp_pe->alproto == ALPROTO_JABBER)
914  printf(" alproto: ALPROTO_JABBER\n");
915  else if (pp_pe->alproto == ALPROTO_SMB)
916  printf(" alproto: ALPROTO_SMB\n");
917  else if (pp_pe->alproto == ALPROTO_DCERPC)
918  printf(" alproto: ALPROTO_DCERPC\n");
919  else if (pp_pe->alproto == ALPROTO_IRC)
920  printf(" alproto: ALPROTO_IRC\n");
921  else if (pp_pe->alproto == ALPROTO_DNS)
922  printf(" alproto: ALPROTO_DNS\n");
923  else if (pp_pe->alproto == ALPROTO_MODBUS)
924  printf(" alproto: ALPROTO_MODBUS\n");
925  else if (pp_pe->alproto == ALPROTO_ENIP)
926  printf(" alproto: ALPROTO_ENIP\n");
927  else if (pp_pe->alproto == ALPROTO_NFS)
928  printf(" alproto: ALPROTO_NFS\n");
929  else if (pp_pe->alproto == ALPROTO_NTP)
930  printf(" alproto: ALPROTO_NTP\n");
931  else if (pp_pe->alproto == ALPROTO_TFTP)
932  printf(" alproto: ALPROTO_TFTP\n");
933  else if (pp_pe->alproto == ALPROTO_IKEV2)
934  printf(" alproto: ALPROTO_IKEV2\n");
935  else if (pp_pe->alproto == ALPROTO_KRB5)
936  printf(" alproto: ALPROTO_KRB5\n");
937  else if (pp_pe->alproto == ALPROTO_DHCP)
938  printf(" alproto: ALPROTO_DHCP\n");
939  else if (pp_pe->alproto == ALPROTO_TEMPLATE_RUST)
940  printf(" alproto: ALPROTO_TEMPLATE_RUST\n");
941  else if (pp_pe->alproto == ALPROTO_TEMPLATE)
942  printf(" alproto: ALPROTO_TEMPLATE\n");
943  else if (pp_pe->alproto == ALPROTO_DNP3)
944  printf(" alproto: ALPROTO_DNP3\n");
945  else
946  printf("impossible\n");
947 
948  printf(" port: %"PRIu16 "\n", pp_pe->port);
949  printf(" mask: %"PRIu32 "\n", pp_pe->alproto_mask);
950  printf(" min_depth: %"PRIu32 "\n", pp_pe->min_depth);
951  printf(" max_depth: %"PRIu32 "\n", pp_pe->max_depth);
952 
953  printf("\n");
954  }
955  }
956  }
957 
958  SCReturn;
959 }
960 #endif
961 
962 static void AppLayerProtoDetectProbingParserElementAppend(AppLayerProtoDetectProbingParserElement **head_pe,
964 {
965  SCEnter();
966 
967  if (*head_pe == NULL) {
968  *head_pe = new_pe;
969  goto end;
970  }
971 
972  if ((*head_pe)->port == 0) {
973  if (new_pe->port != 0) {
974  new_pe->next = *head_pe;
975  *head_pe = new_pe;
976  } else {
977  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
978  while (temp_pe->next != NULL)
979  temp_pe = temp_pe->next;
980  temp_pe->next = new_pe;
981  }
982  } else {
983  AppLayerProtoDetectProbingParserElement *temp_pe = *head_pe;
984  if (new_pe->port == 0) {
985  while (temp_pe->next != NULL)
986  temp_pe = temp_pe->next;
987  temp_pe->next = new_pe;
988  } else {
989  while (temp_pe->next != NULL && temp_pe->next->port != 0)
990  temp_pe = temp_pe->next;
991  new_pe->next = temp_pe->next;
992  temp_pe->next = new_pe;
993 
994  }
995  }
996 
997  end:
998  SCReturn;
999 }
1000 
1001 static void AppLayerProtoDetectProbingParserAppend(AppLayerProtoDetectProbingParser **head_pp,
1003 {
1004  SCEnter();
1005 
1006  if (*head_pp == NULL) {
1007  *head_pp = new_pp;
1008  goto end;
1009  }
1010 
1011  AppLayerProtoDetectProbingParser *temp_pp = *head_pp;
1012  while (temp_pp->next != NULL)
1013  temp_pp = temp_pp->next;
1014  temp_pp->next = new_pp;
1015 
1016  end:
1017  SCReturn;
1018 }
1019 
1020 static void AppLayerProtoDetectProbingParserPortAppend(AppLayerProtoDetectProbingParserPort **head_port,
1022 {
1023  SCEnter();
1024 
1025  if (*head_port == NULL) {
1026  *head_port = new_port;
1027  goto end;
1028  }
1029 
1030  if ((*head_port)->port == 0) {
1031  new_port->next = *head_port;
1032  *head_port = new_port;
1033  } else {
1034  AppLayerProtoDetectProbingParserPort *temp_port = *head_port;
1035  while (temp_port->next != NULL && temp_port->next->port != 0) {
1036  temp_port = temp_port->next;
1037  }
1038  new_port->next = temp_port->next;
1039  temp_port->next = new_port;
1040  }
1041 
1042  end:
1043  SCReturn;
1044 }
1045 
1046 static void AppLayerProtoDetectInsertNewProbingParser(AppLayerProtoDetectProbingParser **pp,
1047  uint8_t ipproto,
1048  uint16_t port,
1049  AppProto alproto,
1050  uint16_t min_depth, uint16_t max_depth,
1051  uint8_t direction,
1052  ProbingParserFPtr ProbingParser1,
1053  ProbingParserFPtr ProbingParser2)
1054 {
1055  SCEnter();
1056 
1057  /* get the top level ipproto pp */
1058  AppLayerProtoDetectProbingParser *curr_pp = *pp;
1059  while (curr_pp != NULL) {
1060  if (curr_pp->ipproto == ipproto)
1061  break;
1062  curr_pp = curr_pp->next;
1063  }
1064  if (curr_pp == NULL) {
1065  AppLayerProtoDetectProbingParser *new_pp = AppLayerProtoDetectProbingParserAlloc();
1066  new_pp->ipproto = ipproto;
1067  AppLayerProtoDetectProbingParserAppend(pp, new_pp);
1068  curr_pp = new_pp;
1069  }
1070 
1071  /* get the top level port pp */
1072  AppLayerProtoDetectProbingParserPort *curr_port = curr_pp->port;
1073  while (curr_port != NULL) {
1074  if (curr_port->port == port)
1075  break;
1076  curr_port = curr_port->next;
1077  }
1078  if (curr_port == NULL) {
1079  AppLayerProtoDetectProbingParserPort *new_port = AppLayerProtoDetectProbingParserPortAlloc();
1080  new_port->port = port;
1081  AppLayerProtoDetectProbingParserPortAppend(&curr_pp->port, new_port);
1082  curr_port = new_port;
1083  if (direction & STREAM_TOSERVER) {
1084  curr_port->dp_max_depth = max_depth;
1085  } else {
1086  curr_port->sp_max_depth = max_depth;
1087  }
1088 
1090 
1091  zero_port = curr_pp->port;
1092  while (zero_port != NULL && zero_port->port != 0) {
1093  zero_port = zero_port->next;
1094  }
1095  if (zero_port != NULL) {
1097 
1098  zero_pe = zero_port->dp;
1099  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1100  if (curr_port->dp == NULL)
1101  curr_port->dp_max_depth = zero_pe->max_depth;
1102  if (zero_pe->max_depth == 0)
1103  curr_port->dp_max_depth = zero_pe->max_depth;
1104  if (curr_port->dp_max_depth != 0 &&
1105  curr_port->dp_max_depth < zero_pe->max_depth) {
1106  curr_port->dp_max_depth = zero_pe->max_depth;
1107  }
1108 
1110  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1111  AppLayerProtoDetectProbingParserElementAppend(&curr_port->dp, dup_pe);
1112  curr_port->alproto_mask |= dup_pe->alproto_mask;
1113  }
1114 
1115  zero_pe = zero_port->sp;
1116  for ( ; zero_pe != NULL; zero_pe = zero_pe->next) {
1117  if (curr_port->sp == NULL)
1118  curr_port->sp_max_depth = zero_pe->max_depth;
1119  if (zero_pe->max_depth == 0)
1120  curr_port->sp_max_depth = zero_pe->max_depth;
1121  if (curr_port->sp_max_depth != 0 &&
1122  curr_port->sp_max_depth < zero_pe->max_depth) {
1123  curr_port->sp_max_depth = zero_pe->max_depth;
1124  }
1125 
1127  AppLayerProtoDetectProbingParserElementDuplicate(zero_pe);
1128  AppLayerProtoDetectProbingParserElementAppend(&curr_port->sp, dup_pe);
1129  curr_port->alproto_mask |= dup_pe->alproto_mask;
1130  }
1131  } /* if (zero_port != NULL) */
1132  } /* if (curr_port == NULL) */
1133 
1134  /* insert the pe_pp */
1136  if (direction & STREAM_TOSERVER)
1137  curr_pe = curr_port->dp;
1138  else
1139  curr_pe = curr_port->sp;
1140  while (curr_pe != NULL) {
1141  if (curr_pe->alproto == alproto) {
1142  SCLogError(SC_ERR_ALPARSER, "Duplicate pp registered - "
1143  "ipproto - %"PRIu8" Port - %"PRIu16" "
1144  "App Protocol - NULL, App Protocol(ID) - "
1145  "%"PRIu16" min_depth - %"PRIu16" "
1146  "max_dept - %"PRIu16".",
1147  ipproto, port, alproto,
1148  min_depth, max_depth);
1149  goto error;
1150  }
1151  curr_pe = curr_pe->next;
1152  }
1153  /* Get a new parser element */
1155  AppLayerProtoDetectProbingParserElementCreate(alproto,
1156  curr_port->port,
1157  min_depth, max_depth);
1158  if (new_pe == NULL)
1159  goto error;
1160  curr_pe = new_pe;
1162  if (direction & STREAM_TOSERVER) {
1163  curr_pe->ProbingParserTs = ProbingParser1;
1164  curr_pe->ProbingParserTc = ProbingParser2;
1165  if (curr_port->dp == NULL)
1166  curr_port->dp_max_depth = new_pe->max_depth;
1167  if (new_pe->max_depth == 0)
1168  curr_port->dp_max_depth = new_pe->max_depth;
1169  if (curr_port->dp_max_depth != 0 &&
1170  curr_port->dp_max_depth < new_pe->max_depth) {
1171  curr_port->dp_max_depth = new_pe->max_depth;
1172  }
1173  curr_port->alproto_mask |= new_pe->alproto_mask;
1174  head_pe = &curr_port->dp;
1175  } else {
1176  curr_pe->ProbingParserTs = ProbingParser2;
1177  curr_pe->ProbingParserTc = ProbingParser1;
1178  if (curr_port->sp == NULL)
1179  curr_port->sp_max_depth = new_pe->max_depth;
1180  if (new_pe->max_depth == 0)
1181  curr_port->sp_max_depth = new_pe->max_depth;
1182  if (curr_port->sp_max_depth != 0 &&
1183  curr_port->sp_max_depth < new_pe->max_depth) {
1184  curr_port->sp_max_depth = new_pe->max_depth;
1185  }
1186  curr_port->alproto_mask |= new_pe->alproto_mask;
1187  head_pe = &curr_port->sp;
1188  }
1189  AppLayerProtoDetectProbingParserElementAppend(head_pe, new_pe);
1190 
1191  if (curr_port->port == 0) {
1192  AppLayerProtoDetectProbingParserPort *temp_port = curr_pp->port;
1193  while (temp_port != NULL && temp_port->port != 0) {
1194  if (direction & STREAM_TOSERVER) {
1195  if (temp_port->dp == NULL)
1196  temp_port->dp_max_depth = curr_pe->max_depth;
1197  if (curr_pe->max_depth == 0)
1198  temp_port->dp_max_depth = curr_pe->max_depth;
1199  if (temp_port->dp_max_depth != 0 &&
1200  temp_port->dp_max_depth < curr_pe->max_depth) {
1201  temp_port->dp_max_depth = curr_pe->max_depth;
1202  }
1203  AppLayerProtoDetectProbingParserElementAppend(&temp_port->dp,
1204  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1205  temp_port->alproto_mask |= curr_pe->alproto_mask;
1206  } else {
1207  if (temp_port->sp == NULL)
1208  temp_port->sp_max_depth = curr_pe->max_depth;
1209  if (curr_pe->max_depth == 0)
1210  temp_port->sp_max_depth = curr_pe->max_depth;
1211  if (temp_port->sp_max_depth != 0 &&
1212  temp_port->sp_max_depth < curr_pe->max_depth) {
1213  temp_port->sp_max_depth = curr_pe->max_depth;
1214  }
1215  AppLayerProtoDetectProbingParserElementAppend(&temp_port->sp,
1216  AppLayerProtoDetectProbingParserElementDuplicate(curr_pe));
1217  temp_port->alproto_mask |= curr_pe->alproto_mask;
1218  }
1219  temp_port = temp_port->next;
1220  } /* while */
1221  } /* if */
1222 
1223  error:
1224  SCReturn;
1225 }
1226 
1227 /***** Static Internal Calls: PM registration *****/
1228 
1229 static void AppLayerProtoDetectPMGetIpprotos(AppProto alproto,
1230  uint8_t *ipprotos)
1231 {
1232  SCEnter();
1233 
1234  for (int i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1235  uint8_t ipproto = FlowGetReverseProtoMapping(i);
1236  for (int j = 0; j < 2; j++) {
1237  AppLayerProtoDetectPMCtx *pm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1238 
1239  for (SigIntId x = 0; x < pm_ctx->max_sig_id; x++) {
1240  const AppLayerProtoDetectPMSignature *s = pm_ctx->map[x];
1241  if (s->alproto == alproto)
1242  ipprotos[ipproto / 8] |= 1 << (ipproto % 8);
1243  }
1244  }
1245  }
1246 
1247  SCReturn;
1248 }
1249 
1250 static int AppLayerProtoDetectPMSetContentIDs(AppLayerProtoDetectPMCtx *ctx)
1251 {
1252  SCEnter();
1253 
1254  typedef struct TempContainer_ {
1255  PatIntId id;
1256  uint16_t content_len;
1257  uint8_t *content;
1258  } TempContainer;
1259 
1261  uint32_t struct_total_size = 0;
1262  uint32_t content_total_size = 0;
1263  /* array hash buffer */
1264  uint8_t *ahb = NULL;
1265  uint8_t *content = NULL;
1266  uint8_t content_len = 0;
1267  PatIntId max_id = 0;
1268  TempContainer *struct_offset = NULL;
1269  uint8_t *content_offset = NULL;
1270  int ret = 0;
1271 
1272  if (ctx->head == NULL)
1273  goto end;
1274 
1275  for (s = ctx->head; s != NULL; s = s->next) {
1276  struct_total_size += sizeof(TempContainer);
1277  content_total_size += s->cd->content_len;
1278  ctx->max_sig_id++;
1279  }
1280 
1281  ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1282  if (unlikely(ahb == NULL))
1283  goto error;
1284 
1285  struct_offset = (TempContainer *)ahb;
1286  content_offset = ahb + struct_total_size;
1287  for (s = ctx->head; s != NULL; s = s->next) {
1288  TempContainer *tcdup = (TempContainer *)ahb;
1289  content = s->cd->content;
1290  content_len = s->cd->content_len;
1291 
1292  for (; tcdup != struct_offset; tcdup++) {
1293  if (tcdup->content_len != content_len ||
1294  SCMemcmp(tcdup->content, content, tcdup->content_len) != 0)
1295  {
1296  continue;
1297  }
1298  break;
1299  }
1300 
1301  if (tcdup != struct_offset) {
1302  s->cd->id = tcdup->id;
1303  continue;
1304  }
1305 
1306  struct_offset->content_len = content_len;
1307  struct_offset->content = content_offset;
1308  content_offset += content_len;
1309  memcpy(struct_offset->content, content, content_len);
1310  struct_offset->id = max_id++;
1311  s->cd->id = struct_offset->id;
1312 
1313  struct_offset++;
1314  }
1315 
1316  ctx->max_pat_id = max_id;
1317 
1318  goto end;
1319  error:
1320  ret = -1;
1321  end:
1322  if (ahb != NULL)
1323  SCFree(ahb);
1324  SCReturnInt(ret);
1325 }
1326 
1327 static int AppLayerProtoDetectPMMapSignatures(AppLayerProtoDetectPMCtx *ctx)
1328 {
1329  SCEnter();
1330 
1331  int ret = 0;
1332  AppLayerProtoDetectPMSignature *s, *next_s;
1333  int mpm_ret;
1334  SigIntId id = 0;
1335 
1336  ctx->map = SCMalloc(ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1337  if (ctx->map == NULL)
1338  goto error;
1339  memset(ctx->map, 0, ctx->max_sig_id * sizeof(AppLayerProtoDetectPMSignature *));
1340 
1341  /* add an array indexed by rule id to look up the sig */
1342  for (s = ctx->head; s != NULL; ) {
1343  next_s = s->next;
1344  s->id = id++;
1345  SCLogDebug("s->id %u offset %u depth %u",
1346  s->id, s->cd->offset, s->cd->depth);
1347 
1348  if (s->cd->flags & DETECT_CONTENT_NOCASE) {
1349  mpm_ret = MpmAddPatternCI(&ctx->mpm_ctx,
1350  s->cd->content, s->cd->content_len,
1351  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1352  if (mpm_ret < 0)
1353  goto error;
1354  } else {
1355  mpm_ret = MpmAddPatternCS(&ctx->mpm_ctx,
1356  s->cd->content, s->cd->content_len,
1357  s->cd->offset, s->cd->depth, s->cd->id, s->id, 0);
1358  if (mpm_ret < 0)
1359  goto error;
1360  }
1361 
1362  ctx->map[s->id] = s;
1363  s->next = NULL;
1364  s = next_s;
1365  }
1366  ctx->head = NULL;
1367 
1368  goto end;
1369  error:
1370  ret = -1;
1371  end:
1372  SCReturnInt(ret);
1373 }
1374 
1375 static int AppLayerProtoDetectPMPrepareMpm(AppLayerProtoDetectPMCtx *ctx)
1376 {
1377  SCEnter();
1378 
1379  int ret = 0;
1380  MpmCtx *mpm_ctx = &ctx->mpm_ctx;
1381 
1382  if (mpm_table[mpm_ctx->mpm_type].Prepare(mpm_ctx) < 0)
1383  goto error;
1384 
1385  goto end;
1386  error:
1387  ret = -1;
1388  end:
1389  SCReturnInt(ret);
1390 }
1391 
1392 static void AppLayerProtoDetectPMFreeSignature(AppLayerProtoDetectPMSignature *sig)
1393 {
1394  SCEnter();
1395  if (sig == NULL)
1396  SCReturn;
1397  if (sig->cd)
1398  DetectContentFree(sig->cd);
1399  SCFree(sig);
1400  SCReturn;
1401 }
1402 
1403 static int AppLayerProtoDetectPMAddSignature(AppLayerProtoDetectPMCtx *ctx, DetectContentData *cd,
1404  AppProto alproto, uint8_t direction,
1405  ProbingParserFPtr PPFunc,
1406  uint16_t pp_min_depth, uint16_t pp_max_depth)
1407 {
1408  SCEnter();
1409 
1410  AppLayerProtoDetectPMSignature *s = SCCalloc(1, sizeof(*s));
1411  if (unlikely(s == NULL))
1412  SCReturnInt(-1);
1413 
1414  s->alproto = alproto;
1415  s->direction = direction;
1416  s->cd = cd;
1417  s->PPFunc = PPFunc;
1418  s->pp_min_depth = pp_min_depth;
1419  s->pp_max_depth = pp_max_depth;
1420 
1421  /* prepend to the list */
1422  s->next = ctx->head;
1423  ctx->head = s;
1424 
1425  SCReturnInt(0);
1426 }
1427 
1428 static int AppLayerProtoDetectPMRegisterPattern(uint8_t ipproto, AppProto alproto,
1429  const char *pattern,
1430  uint16_t depth, uint16_t offset,
1431  uint8_t direction,
1432  uint8_t is_cs,
1433  ProbingParserFPtr PPFunc,
1434  uint16_t pp_min_depth, uint16_t pp_max_depth)
1435 {
1436  SCEnter();
1437 
1438  AppLayerProtoDetectCtxIpproto *ctx_ipp = &alpd_ctx.ctx_ipp[FlowGetProtoMapping(ipproto)];
1439  AppLayerProtoDetectPMCtx *ctx_pm = NULL;
1440  int ret = 0;
1441 
1443  alpd_ctx.spm_global_thread_ctx, pattern);
1444  if (cd == NULL)
1445  goto error;
1446  cd->depth = depth;
1447  cd->offset = offset;
1448  if (!is_cs) {
1449  /* Rebuild as nocase */
1450  SpmDestroyCtx(cd->spm_ctx);
1451  cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 1,
1452  alpd_ctx.spm_global_thread_ctx);
1453  if (cd->spm_ctx == NULL) {
1454  goto error;
1455  }
1457  }
1458  if (depth < cd->content_len)
1459  goto error;
1460 
1461  if (direction & STREAM_TOSERVER)
1462  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[0];
1463  else
1464  ctx_pm = (AppLayerProtoDetectPMCtx *)&ctx_ipp->ctx_pm[1];
1465 
1466  if (pp_max_depth > ctx_pm->pp_max_len)
1467  ctx_pm->pp_max_len = pp_max_depth;
1468  if (depth < ctx_pm->min_len)
1469  ctx_pm->min_len = depth;
1470 
1471  /* Finally turn it into a signature and add to the ctx. */
1472  AppLayerProtoDetectPMAddSignature(ctx_pm, cd, alproto, direction,
1473  PPFunc, pp_min_depth, pp_max_depth);
1474 
1475  goto end;
1476  error:
1477  ret = -1;
1478  end:
1479  SCReturnInt(ret);
1480 }
1481 
1482 /***** Protocol Retrieval *****/
1483 
1485  Flow *f,
1486  uint8_t *buf, uint32_t buflen,
1487  uint8_t ipproto, uint8_t direction,
1488  bool *reverse_flow)
1489 {
1490  SCEnter();
1491  SCLogDebug("buflen %u for %s direction", buflen,
1492  (direction & STREAM_TOSERVER) ? "toserver" : "toclient");
1493 
1494  AppProto alproto = ALPROTO_UNKNOWN;
1495  AppProto pm_alproto = ALPROTO_UNKNOWN;
1496 
1497  if (!FLOW_IS_PM_DONE(f, direction)) {
1498  AppProto pm_results[ALPROTO_MAX];
1499  uint16_t pm_matches = AppLayerProtoDetectPMGetProto(tctx, f,
1500  buf, buflen, direction, pm_results, reverse_flow);
1501  if (pm_matches > 0) {
1502  alproto = pm_results[0];
1503 
1504  /* HACK: if detected protocol is dcerpc/udp, we run PP as well
1505  * to avoid misdetecting DNS as DCERPC. */
1506  if (!(ipproto == IPPROTO_UDP && alproto == ALPROTO_DCERPC))
1507  goto end;
1508 
1509  pm_alproto = alproto;
1510 
1511  /* fall through */
1512  }
1513  }
1514 
1515  if (!FLOW_IS_PP_DONE(f, direction)) {
1516  bool rflow = false;
1517  alproto = AppLayerProtoDetectPPGetProto(f, buf, buflen, ipproto,
1518  direction & (STREAM_TOSERVER|STREAM_TOCLIENT), &rflow);
1519  if (AppProtoIsValid(alproto)) {
1520  if (rflow) {
1521  *reverse_flow = true;
1522  }
1523  goto end;
1524  }
1525  }
1526 
1527  /* Look if flow can be found in expectation list */
1528  if (!FLOW_IS_PE_DONE(f, direction)) {
1529  alproto = AppLayerProtoDetectPEGetProto(f, ipproto, direction);
1530  }
1531 
1532  end:
1533  if (!AppProtoIsValid(alproto))
1534  alproto = pm_alproto;
1535 
1536  SCReturnUInt(alproto);
1537 }
1538 
1539 static void AppLayerProtoDetectFreeProbingParsers(AppLayerProtoDetectProbingParser *pp)
1540 {
1541  SCEnter();
1542 
1543  AppLayerProtoDetectProbingParser *tmp_pp = NULL;
1544 
1545  if (pp == NULL)
1546  goto end;
1547 
1548  while (pp != NULL) {
1549  tmp_pp = pp->next;
1550  AppLayerProtoDetectProbingParserFree(pp);
1551  pp = tmp_pp;
1552  }
1553 
1554  end:
1555  SCReturn;
1556 }
1557 
1558 /***** State Preparation *****/
1559 
1561 {
1562  SCEnter();
1563 
1564  AppLayerProtoDetectPMCtx *ctx_pm;
1565  int i, j;
1566  int ret = 0;
1567 
1568  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1569  for (j = 0; j < 2; j++) {
1570  ctx_pm = &alpd_ctx.ctx_ipp[i].ctx_pm[j];
1571 
1572  if (AppLayerProtoDetectPMSetContentIDs(ctx_pm) < 0)
1573  goto error;
1574 
1575  if (ctx_pm->max_sig_id == 0)
1576  continue;
1577 
1578  if (AppLayerProtoDetectPMMapSignatures(ctx_pm) < 0)
1579  goto error;
1580  if (AppLayerProtoDetectPMPrepareMpm(ctx_pm) < 0)
1581  goto error;
1582  }
1583  }
1584 
1585 #ifdef DEBUG
1586  if (SCLogDebugEnabled()) {
1587  AppLayerProtoDetectPrintProbingParsers(alpd_ctx.ctx_pp);
1588  }
1589 #endif
1590 
1591  goto end;
1592  error:
1593  ret = -1;
1594  end:
1595  SCReturnInt(ret);
1596 }
1597 
1598 /***** PP registration *****/
1599 
1600 /** \brief register parser at a port
1601  *
1602  * \param direction STREAM_TOSERVER or STREAM_TOCLIENT for dp or sp
1603  */
1604 void AppLayerProtoDetectPPRegister(uint8_t ipproto,
1605  const char *portstr,
1606  AppProto alproto,
1607  uint16_t min_depth, uint16_t max_depth,
1608  uint8_t direction,
1609  ProbingParserFPtr ProbingParser1,
1610  ProbingParserFPtr ProbingParser2)
1611 {
1612  SCEnter();
1613 
1614  DetectPort *head = NULL;
1615  DetectPortParse(NULL,&head, portstr);
1616  DetectPort *temp_dp = head;
1617  while (temp_dp != NULL) {
1618  uint32_t port = temp_dp->port;
1619  if (port == 0 && temp_dp->port2 != 0)
1620  port++;
1621  for ( ; port <= temp_dp->port2; port++) {
1622  AppLayerProtoDetectInsertNewProbingParser(&alpd_ctx.ctx_pp,
1623  ipproto,
1624  port,
1625  alproto,
1626  min_depth, max_depth,
1627  direction,
1628  ProbingParser1,
1629  ProbingParser2);
1630  }
1631  temp_dp = temp_dp->next;
1632  }
1633  DetectPortCleanupList(NULL,head);
1634 
1635  SCReturn;
1636 }
1637 
1638 int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name,
1639  uint8_t ipproto,
1640  const char *alproto_name,
1641  AppProto alproto,
1642  uint16_t min_depth, uint16_t max_depth,
1645 {
1646  SCEnter();
1647 
1648  char param[100];
1649  int r;
1650  ConfNode *node;
1651  ConfNode *port_node = NULL;
1652  int config = 0;
1653 
1654  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1655  alproto_name, ".detection-ports");
1656  if (r < 0) {
1657  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1658  exit(EXIT_FAILURE);
1659  } else if (r > (int)sizeof(param)) {
1660  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1661  exit(EXIT_FAILURE);
1662  }
1663  node = ConfGetNode(param);
1664  if (node == NULL) {
1665  SCLogDebug("Entry for %s not found.", param);
1666  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1667  alproto_name, ".", ipproto_name, ".detection-ports");
1668  if (r < 0) {
1669  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1670  exit(EXIT_FAILURE);
1671  } else if (r > (int)sizeof(param)) {
1672  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1673  exit(EXIT_FAILURE);
1674  }
1675  node = ConfGetNode(param);
1676  if (node == NULL)
1677  goto end;
1678  }
1679 
1680  /* detect by destination port of the flow (e.g. port 53 for DNS) */
1681  port_node = ConfNodeLookupChild(node, "dp");
1682  if (port_node == NULL)
1683  port_node = ConfNodeLookupChild(node, "toserver");
1684 
1685  if (port_node != NULL && port_node->val != NULL) {
1687  port_node->val,
1688  alproto,
1689  min_depth, max_depth,
1690  STREAM_TOSERVER, /* to indicate dp */
1691  ProbingParserTs, ProbingParserTc);
1692  }
1693 
1694  /* detect by source port of flow */
1695  port_node = ConfNodeLookupChild(node, "sp");
1696  if (port_node == NULL)
1697  port_node = ConfNodeLookupChild(node, "toclient");
1698 
1699  if (port_node != NULL && port_node->val != NULL) {
1701  port_node->val,
1702  alproto,
1703  min_depth, max_depth,
1704  STREAM_TOCLIENT, /* to indicate sp */
1705  ProbingParserTc, ProbingParserTs);
1706 
1707  }
1708 
1709  config = 1;
1710  end:
1711  SCReturnInt(config);
1712 }
1713 
1714 /***** PM registration *****/
1715 
1717  const char *pattern,
1718  uint16_t depth, uint16_t offset,
1719  uint8_t direction)
1720 {
1721  SCEnter();
1722  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1723  pattern, depth, offset,
1724  direction, 1 /* case-sensitive */,
1725  NULL, 0, 0);
1726  SCReturnInt(r);
1727 }
1728 
1730  const char *pattern, uint16_t depth, uint16_t offset,
1731  uint8_t direction,
1732  ProbingParserFPtr PPFunc,
1733  uint16_t pp_min_depth, uint16_t pp_max_depth)
1734 {
1735  SCEnter();
1736  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1737  pattern, depth, offset,
1738  direction, 1 /* case-sensitive */,
1739  PPFunc, pp_min_depth, pp_max_depth);
1740  SCReturnInt(r);
1741 }
1742 
1744  const char *pattern,
1745  uint16_t depth, uint16_t offset,
1746  uint8_t direction)
1747 {
1748  SCEnter();
1749  int r = AppLayerProtoDetectPMRegisterPattern(ipproto, alproto,
1750  pattern, depth, offset,
1751  direction, 0 /* !case-sensitive */,
1752  NULL, 0, 0);
1753  SCReturnInt(r);
1754 }
1755 
1756 /***** Setup/General Registration *****/
1757 
1759 {
1760  SCEnter();
1761 
1762  int i, j;
1763 
1764  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
1765 
1766  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1767  uint16_t mpm_matcher = PatternMatchDefaultMatcher();
1768 
1769  alpd_ctx.spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1770  if (alpd_ctx.spm_global_thread_ctx == NULL) {
1771  SCLogError(SC_ERR_FATAL, "Unable to alloc SpmGlobalThreadCtx.");
1772  exit(EXIT_FAILURE);
1773  }
1774 
1775  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1776  for (j = 0; j < 2; j++) {
1777  MpmInitCtx(&alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx, mpm_matcher);
1778  }
1779  }
1780 
1782 
1783  SCReturnInt(0);
1784 }
1785 
1786 /**
1787  * \todo incomplete. Need more work.
1788  */
1790 {
1791  SCEnter();
1792 
1793  int ipproto_map = 0;
1794  int dir = 0;
1795  PatIntId id = 0;
1796  AppLayerProtoDetectPMCtx *pm_ctx = NULL;
1797  AppLayerProtoDetectPMSignature *sig = NULL;
1798 
1799  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
1800  for (dir = 0; dir < 2; dir++) {
1801  pm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir];
1802  mpm_table[pm_ctx->mpm_ctx.mpm_type].DestroyCtx(&pm_ctx->mpm_ctx);
1803  for (id = 0; id < pm_ctx->max_sig_id; id++) {
1804  sig = pm_ctx->map[id];
1805  AppLayerProtoDetectPMFreeSignature(sig);
1806  }
1807  SCFree(pm_ctx->map);
1808  pm_ctx->map = NULL;
1809  }
1810  }
1811 
1813 
1814  AppLayerProtoDetectFreeProbingParsers(alpd_ctx.ctx_pp);
1815 
1816  SCReturnInt(0);
1817 }
1818 
1819 void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
1820 {
1821  SCEnter();
1822 
1823  if (alpd_ctx.alproto_names[alproto] == NULL)
1824  alpd_ctx.alproto_names[alproto] = alproto_name;
1825 
1826  SCReturn;
1827 }
1828 
1829 /** \brief request applayer to wrap up this protocol and rerun protocol
1830  * detection.
1831  *
1832  * When this is called, the old session is reset unconditionally. A
1833  * 'detect/log' flush packet is generated for both direction before
1834  * the reset, so allow for final detection and logging.
1835  *
1836  * \param f flow to act on
1837  * \param dp destination port to use in protocol detection. Set to 443
1838  * for start tls, set to the HTTP uri port for CONNECT and
1839  * set to 0 to not use it.
1840  * \param expect_proto expected protocol. AppLayer event will be set if
1841  * detected protocol differs from this.
1842  */
1843 void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
1844 {
1846  f->protodetect_dp = dp;
1847  f->alproto_expect = expect_proto;
1848 }
1849 
1850 /** \brief request applayer to wrap up this protocol and rerun protocol
1851  * detection with expectation of TLS. Used by STARTTLS.
1852  *
1853  * Sets detection port to 443 to make port based TLS detection work for
1854  * SMTP, FTP etc as well.
1855  *
1856  * \param f flow to act on
1857  */
1859 {
1861 }
1862 
1864 {
1866  FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
1868  FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
1870  FLOW_RESET_PE_DONE(f, STREAM_TOSERVER);
1874 
1876  f->alstate = NULL;
1877  f->alparser = NULL;
1878  f->alproto = ALPROTO_UNKNOWN;
1881 }
1882 
1884  const char *alproto)
1885 {
1886  SCEnter();
1887 
1888  BUG_ON(ipproto == NULL || alproto == NULL);
1889 
1890  int enabled = 1;
1891  char param[100];
1892  ConfNode *node;
1893  int r;
1894 
1895 #ifdef AFLFUZZ_APPLAYER
1896  goto enabled;
1897 #endif
1898  if (RunmodeIsUnittests())
1899  goto enabled;
1900 
1901  r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.",
1902  alproto, ".enabled");
1903  if (r < 0) {
1904  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1905  exit(EXIT_FAILURE);
1906  } else if (r > (int)sizeof(param)) {
1907  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1908  exit(EXIT_FAILURE);
1909  }
1910 
1911  node = ConfGetNode(param);
1912  if (node == NULL) {
1913  SCLogDebug("Entry for %s not found.", param);
1914  r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.",
1915  alproto, ".", ipproto, ".enabled");
1916  if (r < 0) {
1917  SCLogError(SC_ERR_FATAL, "snprintf failure.");
1918  exit(EXIT_FAILURE);
1919  } else if (r > (int)sizeof(param)) {
1920  SCLogError(SC_ERR_FATAL, "buffer not big enough to write param.");
1921  exit(EXIT_FAILURE);
1922  }
1923 
1924  node = ConfGetNode(param);
1925  if (node == NULL) {
1926  SCLogDebug("Entry for %s not found.", param);
1927  goto enabled;
1928  }
1929  }
1930 
1931  if (node->val) {
1932  if (ConfValIsTrue(node->val)) {
1933  goto enabled;
1934  } else if (ConfValIsFalse(node->val)) {
1935  goto disabled;
1936  } else if (strcasecmp(node->val, "detection-only") == 0) {
1937  goto enabled;
1938  }
1939  }
1940 
1941  /* Invalid or null value. */
1942  SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param);
1943  exit(EXIT_FAILURE);
1944 
1945  disabled:
1946  enabled = 0;
1947  enabled:
1948  SCReturnInt(enabled);
1949 }
1950 
1952 {
1953  SCEnter();
1954 
1955  AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
1956  MpmCtx *mpm_ctx;
1957  MpmThreadCtx *mpm_tctx;
1958  int i, j;
1959  PatIntId max_pat_id = 0;
1960 
1961  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1962  for (j = 0; j < 2; j++) {
1963  if (max_pat_id == 0) {
1964  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1965 
1966  } else if (alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id &&
1967  max_pat_id < alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id)
1968  {
1969  max_pat_id = alpd_ctx.ctx_ipp[i].ctx_pm[j].max_pat_id;
1970  }
1971  }
1972  }
1973 
1974  alpd_tctx = SCMalloc(sizeof(*alpd_tctx));
1975  if (alpd_tctx == NULL)
1976  goto error;
1977  memset(alpd_tctx, 0, sizeof(*alpd_tctx));
1978 
1979  /* Get the max pat id for all the mpm ctxs. */
1980  if (PmqSetup(&alpd_tctx->pmq) < 0)
1981  goto error;
1982 
1983  for (i = 0; i < FLOW_PROTO_DEFAULT; i++) {
1984  for (j = 0; j < 2; j++) {
1985  mpm_ctx = &alpd_ctx.ctx_ipp[i].ctx_pm[j].mpm_ctx;
1986  mpm_tctx = &alpd_tctx->mpm_tctx[i][j];
1987  mpm_table[mpm_ctx->mpm_type].InitThreadCtx(mpm_ctx, mpm_tctx);
1988  }
1989  }
1990 
1991  alpd_tctx->spm_thread_ctx = SpmMakeThreadCtx(alpd_ctx.spm_global_thread_ctx);
1992  if (alpd_tctx->spm_thread_ctx == NULL) {
1993  goto error;
1994  }
1995 
1996  goto end;
1997  error:
1998  if (alpd_tctx != NULL)
2000  alpd_tctx = NULL;
2001  end:
2002  SCReturnPtr(alpd_tctx, "AppLayerProtoDetectThreadCtx");
2003 }
2004 
2006 {
2007  SCEnter();
2008 
2009  MpmCtx *mpm_ctx;
2010  MpmThreadCtx *mpm_tctx;
2011  int ipproto_map, dir;
2012 
2013  for (ipproto_map = 0; ipproto_map < FLOW_PROTO_DEFAULT; ipproto_map++) {
2014  for (dir = 0; dir < 2; dir++) {
2015  mpm_ctx = &alpd_ctx.ctx_ipp[ipproto_map].ctx_pm[dir].mpm_ctx;
2016  mpm_tctx = &alpd_tctx->mpm_tctx[ipproto_map][dir];
2017  mpm_table[mpm_ctx->mpm_type].DestroyThreadCtx(mpm_ctx, mpm_tctx);
2018  }
2019  }
2020  PmqFree(&alpd_tctx->pmq);
2021  if (alpd_tctx->spm_thread_ctx != NULL) {
2022  SpmDestroyThreadCtx(alpd_tctx->spm_thread_ctx);
2023  }
2024  SCFree(alpd_tctx);
2025 
2026  SCReturn;
2027 }
2028 
2029 /***** Utility *****/
2030 
2031 void AppLayerProtoDetectSupportedIpprotos(AppProto alproto, uint8_t *ipprotos)
2032 {
2033  SCEnter();
2034 
2035  AppLayerProtoDetectPMGetIpprotos(alproto, ipprotos);
2036  AppLayerProtoDetectPPGetIpprotos(alproto, ipprotos);
2037  AppLayerProtoDetectPEGetIpprotos(alproto, ipprotos);
2038 
2039  SCReturn;
2040 }
2041 
2043 {
2044  SCEnter();
2045 
2046  AppProto a;
2047  for (a = 0; a < ALPROTO_MAX; a++) {
2048  if (alpd_ctx.alproto_names[a] != NULL &&
2049  strlen(alpd_ctx.alproto_names[a]) == strlen(alproto_name) &&
2050  (SCMemcmp(alpd_ctx.alproto_names[a], alproto_name, strlen(alproto_name)) == 0))
2051  {
2052  SCReturnCT(a, "AppProto");
2053  }
2054  }
2055 
2056  SCReturnCT(ALPROTO_UNKNOWN, "AppProto");
2057 }
2058 
2060 {
2061  return alpd_ctx.alproto_names[alproto];
2062 }
2063 
2065 {
2066  SCEnter();
2067 
2068  memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto));
2069 
2070  int alproto;
2071 
2072  for (alproto = 0; alproto != ALPROTO_MAX; alproto++) {
2073  if (alpd_ctx.alproto_names[alproto] != NULL)
2074  alprotos[alproto] = 1;
2075  }
2076 
2077  SCReturn;
2078 }
2079 
2081 
2082 static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto,
2083  uint8_t *ipprotos)
2084 {
2085  if (expectation_proto[alproto] == IPPROTO_TCP) {
2086  ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
2087  }
2088  if (expectation_proto[alproto] == IPPROTO_UDP) {
2089  ipprotos[IPPROTO_UDP / 8] |= 1 << (IPPROTO_UDP % 8);
2090  }
2091 }
2092 
2093 void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
2094 {
2095  if (expectation_proto[alproto]) {
2096  if (proto != expectation_proto[alproto]) {
2098  "Expectation on 2 IP protocols are not supported");
2099  }
2100  }
2101  expectation_proto[alproto] = proto;
2102 }
2103 
2104 /***** Unittests *****/
2105 
2106 #ifdef UNITTESTS
2107 
2108 #include "app-layer-htp.h"
2109 
2110 static AppLayerProtoDetectCtx alpd_ctx_ut;
2111 
2113 {
2114  SCEnter();
2115  alpd_ctx_ut = alpd_ctx;
2116  memset(&alpd_ctx, 0, sizeof(alpd_ctx));
2117  SCReturn;
2118 }
2119 
2121 {
2122  SCEnter();
2123  alpd_ctx = alpd_ctx_ut;
2124  memset(&alpd_ctx_ut, 0, sizeof(alpd_ctx_ut));
2125  SCReturn;
2126 }
2127 
2128 static int AppLayerProtoDetectTest01(void)
2129 {
2132 
2133  const char *buf = "HTTP";
2135  buf = "GET";
2136  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, buf, 4, 0, STREAM_TOSERVER);
2137 
2139  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1);
2140  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2141 
2144  PASS;
2145 }
2146 
2147 static int AppLayerProtoDetectTest02(void)
2148 {
2151 
2152  const char *buf = "HTTP";
2154  buf = "ftp";
2156 
2158  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2159  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2160 
2161  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2162  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2163 
2166 
2169  PASS;
2170 }
2171 
2172 static int AppLayerProtoDetectTest03(void)
2173 {
2176 
2177  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2178  AppProto pm_results[ALPROTO_MAX];
2179  memset(pm_results, 0, sizeof(pm_results));
2180  Flow f;
2181  memset(&f, 0x00, sizeof(f));
2182  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2183 
2184 
2185  const char *buf = "HTTP";
2187  buf = "220 ";
2189 
2191  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2192  * it sets internal structures which depends on the above function. */
2194  FAIL_IF_NULL(alpd_tctx);
2195 
2196  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2197  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2198  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2199  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2202 
2203  bool rflow = false;
2204  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2205  &f, l7data, sizeof(l7data),
2207  pm_results, &rflow);
2208  FAIL_IF(cnt != 1);
2209  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2210 
2214  PASS;
2215 }
2216 
2217 static int AppLayerProtoDetectTest04(void)
2218 {
2221 
2222  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n";
2223  Flow f;
2224  memset(&f, 0x00, sizeof(f));
2225  AppProto pm_results[ALPROTO_MAX];
2226  memset(pm_results, 0, sizeof(pm_results));
2227  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2228 
2229  const char *buf = "200 ";
2231 
2233  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2234  * it sets internal structures which depends on the above function. */
2236  FAIL_IF_NULL(alpd_tctx);
2237 
2238  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2239  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2240  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2241  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2243 
2244  bool rdir = false;
2245  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2246  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2247  pm_results, &rdir);
2248  FAIL_IF(cnt != 1);
2249  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2250 
2254  PASS;
2255 }
2256 
2257 static int AppLayerProtoDetectTest05(void)
2258 {
2261 
2262  uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n<HTML><BODY>Blahblah</BODY></HTML>";
2263  AppProto pm_results[ALPROTO_MAX];
2264  memset(pm_results, 0, sizeof(pm_results));
2265  Flow f;
2266  memset(&f, 0x00, sizeof(f));
2267  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2268 
2269  const char *buf = "HTTP";
2271  buf = "220 ";
2273 
2275  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2276  * it sets internal structures which depends on the above function. */
2278  FAIL_IF_NULL(alpd_tctx);
2279 
2280  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2281  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2282  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2283  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2286 
2287  bool rdir = false;
2288  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2289  &f, l7data, sizeof(l7data),
2291  pm_results, &rdir);
2292  FAIL_IF(cnt != 1);
2293  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2294 
2298  PASS;
2299 }
2300 
2301 static int AppLayerProtoDetectTest06(void)
2302 {
2305 
2306  uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n";
2307  AppProto pm_results[ALPROTO_MAX];
2308  memset(pm_results, 0, sizeof(pm_results));
2309  Flow f;
2310  memset(&f, 0x00, sizeof(f));
2311  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2312 
2313  const char *buf = "HTTP";
2315  buf = "220 ";
2317 
2319  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2320  * it sets internal structures which depends on the above function. */
2322  FAIL_IF_NULL(alpd_tctx);
2323 
2324  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2325  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 2);
2326  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2327  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2330 
2331  bool rdir = false;
2332  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2333  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2334  pm_results, &rdir);
2335  FAIL_IF(cnt != 1);
2336  FAIL_IF(pm_results[0] != ALPROTO_FTP);
2337 
2341  PASS;
2342 }
2343 
2344 static int AppLayerProtoDetectTest07(void)
2345 {
2348 
2349  uint8_t l7data[] = "220 Welcome to the OISF HTTP/FTP server\r\n";
2350  Flow f;
2351  memset(&f, 0x00, sizeof(f));
2352  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2353  AppProto pm_results[ALPROTO_MAX];
2354  memset(pm_results, 0, sizeof(pm_results));
2355 
2356  const char *buf = "HTTP";
2358 
2360  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2361  * it sets internal structures which depends on the above function. */
2363 
2364  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2365  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2366  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2367  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2369 
2370  bool rdir = false;
2371  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2372  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2373  pm_results, &rdir);
2374  FAIL_IF(cnt != 0);
2375 
2379  PASS;
2380 }
2381 
2382 static int AppLayerProtoDetectTest08(void)
2383 {
2386 
2387  uint8_t l7data[] = {
2388  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2389  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2390  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2391  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2392  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2393  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2394  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2395  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2396  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2397  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2398  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2399  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2400  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2401  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2402  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2403  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2404  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2405  0x00
2406  };
2407  AppProto pm_results[ALPROTO_MAX];
2408  memset(pm_results, 0, sizeof(pm_results));
2409  Flow f;
2410  memset(&f, 0x00, sizeof(f));
2411  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2412 
2413  const char *buf = "|ff|SMB";
2415 
2417  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2418  * it sets internal structures which depends on the above function. */
2420  FAIL_IF_NULL(alpd_tctx);
2421 
2422  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2423  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2424  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2425  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2427 
2428  bool rdir = false;
2429  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2430  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2431  pm_results, &rdir);
2432  FAIL_IF(cnt != 1);
2433  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2434 
2438  PASS;
2439 }
2440 
2441 static int AppLayerProtoDetectTest09(void)
2442 {
2445 
2446  uint8_t l7data[] = {
2447  0x00, 0x00, 0x00, 0x66, 0xfe, 0x53, 0x4d, 0x42,
2448  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2449  0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
2450  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2451  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2452  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2453  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2454  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2455  0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x00,
2456  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2457  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2458  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2459  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2460  0x00, 0x02, 0x02
2461  };
2462  AppProto pm_results[ALPROTO_MAX];
2463  memset(pm_results, 0, sizeof(pm_results));
2464  Flow f;
2465  memset(&f, 0x00, sizeof(f));
2466  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2467 
2468  const char *buf = "|fe|SMB";
2470 
2472  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2473  * it sets internal structures which depends on the above function. */
2475  FAIL_IF_NULL(alpd_tctx);
2476 
2477  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2478  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2479  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2480  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2482 
2483  bool rdir = false;
2484  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2485  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2486  pm_results, &rdir);
2487  FAIL_IF(cnt != 1);
2488  FAIL_IF(pm_results[0] != ALPROTO_SMB);
2489 
2493  PASS;
2494 }
2495 
2496 static int AppLayerProtoDetectTest10(void)
2497 {
2500 
2501  uint8_t l7data[] = {
2502  0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
2503  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2504  0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
2505  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2506  0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11,
2507  0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57,
2508  0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
2509  0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
2510  0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00
2511  };
2512  AppProto pm_results[ALPROTO_MAX];
2513  memset(pm_results, 0, sizeof(pm_results));
2514  Flow f;
2515  memset(&f, 0x00, sizeof(f));
2516  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2517 
2518  const char *buf = "|05 00|";
2520 
2522  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2523  * it sets internal structures which depends on the above function. */
2525  FAIL_IF_NULL(alpd_tctx);
2526 
2527  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 0);
2528  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2529  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL);
2530  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2532 
2533  bool rdir = false;
2534  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2535  &f, l7data, sizeof(l7data), STREAM_TOCLIENT,
2536  pm_results, &rdir);
2537  FAIL_IF(cnt != 1);
2538  FAIL_IF(pm_results[0] != ALPROTO_DCERPC);
2539 
2543  PASS;
2544 }
2545 
2546 /**
2547  * \test Why we still get http for connect... obviously because
2548  * we also match on the reply, duh
2549  */
2550 static int AppLayerProtoDetectTest11(void)
2551 {
2554 
2555  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2556  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2557  AppProto pm_results[ALPROTO_MAX];
2558  memset(pm_results, 0, sizeof(pm_results));
2559  Flow f;
2560  memset(&f, 0x00, sizeof(f));
2561  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2562 
2563  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2564  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2565  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2566  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2567  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2568  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2569  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2571 
2573  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2574  * it sets internal structures which depends on the above function. */
2576  FAIL_IF_NULL(alpd_tctx);
2577 
2578  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 7);
2579  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].max_pat_id != 1);
2580  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL);
2581  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[1].map == NULL);
2582 
2591 
2592  bool rdir = false;
2593  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2594  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2595  pm_results, &rdir);
2596  FAIL_IF(cnt != 1);
2597  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2598 
2599  memset(pm_results, 0, sizeof(pm_results));
2600  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2601  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2602  pm_results, &rdir);
2603  FAIL_IF(cnt != 1);
2604  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2605 
2609  PASS;
2610 }
2611 
2612 /**
2613  * \test AlpProtoSignature test
2614  */
2615 static int AppLayerProtoDetectTest12(void)
2616 {
2619 
2620  int r = 0;
2621 
2622  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2623  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head == NULL ||
2624  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map != NULL)
2625  {
2626  printf("failure 1\n");
2627  goto end;
2628  }
2629 
2631  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].max_pat_id != 1) {
2632  printf("failure 2\n");
2633  goto end;
2634  }
2635  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].head != NULL ||
2636  alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map == NULL)
2637  {
2638  printf("failure 3\n");
2639  goto end;
2640  }
2641  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->alproto != ALPROTO_HTTP) {
2642  printf("failure 4\n");
2643  goto end;
2644  }
2645  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->cd->id != 0) {
2646  printf("failure 5\n");
2647  goto end;
2648  }
2649  if (alpd_ctx.ctx_ipp[FLOW_PROTO_TCP].ctx_pm[0].map[0]->next != NULL) {
2650  printf("failure 6\n");
2651  goto end;
2652  }
2653 
2654  r = 1;
2655 
2656  end:
2659  return r;
2660 }
2661 
2662 /**
2663  * \test What about if we add some sigs only for udp but call for tcp?
2664  * It should not detect any proto
2665  */
2666 static int AppLayerProtoDetectTest13(void)
2667 {
2670 
2671  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2672  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2673  AppProto pm_results[ALPROTO_MAX];
2674 
2675  Flow f;
2676  memset(&f, 0x00, sizeof(f));
2677  f.protomap = FlowGetProtoMapping(IPPROTO_TCP);
2678 
2679  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2680  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2681  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2682  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2683  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2684  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2685  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2687 
2689  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2690  * it sets internal structures which depends on the above function. */
2692 
2693  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2694  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2695 
2704 
2705  memset(pm_results, 0, sizeof(pm_results));
2706  bool rdir = false;
2707  uint32_t cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2708  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2709  pm_results, &rdir);
2710  FAIL_IF(cnt != 0);
2711 
2712  memset(pm_results, 0, sizeof(pm_results));
2713  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2714  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2715  pm_results, &rdir);
2716  FAIL_IF(cnt != 0);
2717 
2721  PASS;
2722 }
2723 
2724 /**
2725  * \test What about if we add some sigs only for udp calling it for UDP?
2726  * It should detect ALPROTO_HTTP (over udp). This is just a check
2727  * to ensure that TCP/UDP differences work correctly.
2728  */
2729 static int AppLayerProtoDetectTest14(void)
2730 {
2733 
2734  uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n";
2735  uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n";
2736  AppProto pm_results[ALPROTO_MAX];
2737  uint32_t cnt;
2738  Flow f;
2739  memset(&f, 0x00, sizeof(f));
2740  f.protomap = FlowGetProtoMapping(IPPROTO_UDP);
2741 
2742  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "HTTP", 4, 0, STREAM_TOSERVER);
2743  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "GET", 3, 0, STREAM_TOSERVER);
2744  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "PUT", 3, 0, STREAM_TOSERVER);
2745  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "POST", 4, 0, STREAM_TOSERVER);
2746  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "TRACE", 5, 0, STREAM_TOSERVER);
2747  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "OPTIONS", 7, 0, STREAM_TOSERVER);
2748  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_HTTP, "CONNECT", 7, 0, STREAM_TOSERVER);
2750 
2752  /* AppLayerProtoDetectGetCtxThread() should be called post AppLayerProtoDetectPrepareState(), since
2753  * it sets internal structures which depends on the above function. */
2755  FAIL_IF_NULL(alpd_tctx);
2756 
2757  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[0].max_pat_id != 7);
2758  FAIL_IF(alpd_ctx.ctx_ipp[FLOW_PROTO_UDP].ctx_pm[1].max_pat_id != 1);
2759 
2768 
2769  memset(pm_results, 0, sizeof(pm_results));
2770  bool rdir = false;
2771  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2772  &f, l7data, sizeof(l7data), STREAM_TOSERVER,
2773  pm_results, &rdir);
2774  FAIL_IF(cnt != 1);
2775  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2776 
2777  memset(pm_results, 0, sizeof(pm_results));
2778  cnt = AppLayerProtoDetectPMGetProto(alpd_tctx,
2779  &f, l7data_resp, sizeof(l7data_resp), STREAM_TOCLIENT,
2780  pm_results, &rdir);
2781  FAIL_IF(cnt != 1);
2782  FAIL_IF(pm_results[0] != ALPROTO_HTTP);
2783 
2787  PASS;
2788 }
2789 
2791  const char *alproto_name;
2793  uint16_t port;
2794  uint32_t alproto_mask;
2795  uint32_t min_depth;
2796  uint32_t max_depth;
2798 
2800  uint16_t port;
2801  uint32_t alproto_mask;
2802  uint16_t dp_max_depth;
2803  uint16_t sp_max_depth;
2804 
2810 
2811 
2813  uint8_t ipproto;
2814 
2818 
2819 static int AppLayerProtoDetectPPTestData(AppLayerProtoDetectProbingParser *pp,
2821  int no_of_ip_proto)
2822 {
2823  int result = 0;
2824  int i = -1, j = -1 , k = -1;
2825 #ifdef DEBUG
2826  int dir = 0;
2827 #endif
2828  for (i = 0; i < no_of_ip_proto; i++, pp = pp->next) {
2829  if (pp->ipproto != ip_proto[i].ipproto)
2830  goto end;
2831 
2833  for (k = 0; k < ip_proto[i].no_of_port; k++, pp_port = pp_port->next) {
2834  if (pp_port->port != ip_proto[i].port[k].port)
2835  goto end;
2836  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2837  goto end;
2838  if (pp_port->alproto_mask != ip_proto[i].port[k].alproto_mask)
2839  goto end;
2840  if (pp_port->dp_max_depth != ip_proto[i].port[k].dp_max_depth)
2841  goto end;
2842  if (pp_port->sp_max_depth != ip_proto[i].port[k].sp_max_depth)
2843  goto end;
2844 
2845  AppLayerProtoDetectProbingParserElement *pp_element = pp_port->dp;
2846 #ifdef DEBUG
2847  dir = 0;
2848 #endif
2849  for (j = 0 ; j < ip_proto[i].port[k].ts_no_of_element;
2850  j++, pp_element = pp_element->next) {
2851 
2852  if (pp_element->alproto != ip_proto[i].port[k].toserver_element[j].alproto) {
2853  goto end;
2854  }
2855  if (pp_element->port != ip_proto[i].port[k].toserver_element[j].port) {
2856  goto end;
2857  }
2858  if (pp_element->alproto_mask != ip_proto[i].port[k].toserver_element[j].alproto_mask) {
2859  goto end;
2860  }
2861  if (pp_element->min_depth != ip_proto[i].port[k].toserver_element[j].min_depth) {
2862  goto end;
2863  }
2864  if (pp_element->max_depth != ip_proto[i].port[k].toserver_element[j].max_depth) {
2865  goto end;
2866  }
2867  } /* for */
2868  if (pp_element != NULL)
2869  goto end;
2870 
2871  pp_element = pp_port->sp;
2872 #ifdef DEBUG
2873  dir = 1;
2874 #endif
2875  for (j = 0 ; j < ip_proto[i].port[k].tc_no_of_element; j++, pp_element = pp_element->next) {
2876  if (pp_element->alproto != ip_proto[i].port[k].toclient_element[j].alproto) {
2877  goto end;
2878  }
2879  if (pp_element->port != ip_proto[i].port[k].toclient_element[j].port) {
2880  goto end;
2881  }
2882  if (pp_element->alproto_mask != ip_proto[i].port[k].toclient_element[j].alproto_mask) {
2883  goto end;
2884  }
2885  if (pp_element->min_depth != ip_proto[i].port[k].toclient_element[j].min_depth) {
2886  goto end;
2887  }
2888  if (pp_element->max_depth != ip_proto[i].port[k].toclient_element[j].max_depth) {
2889  goto end;
2890  }
2891  } /* for */
2892  if (pp_element != NULL)
2893  goto end;
2894  }
2895  if (pp_port != NULL)
2896  goto end;
2897  }
2898  if (pp != NULL)
2899  goto end;
2900 
2901  result = 1;
2902  end:
2903 #ifdef DEBUG
2904  printf("i = %d, k = %d, j = %d(%s)\n", i, k, j, (dir == 0) ? "ts" : "tc");
2905 #endif
2906  return result;
2907 }
2908 
2909 static uint16_t ProbingParserDummyForTesting(Flow *f, uint8_t direction,
2910  uint8_t *input,
2911  uint32_t input_len, uint8_t *rdir)
2912 {
2913  return 0;
2914 }
2915 
2916 static int AppLayerProtoDetectTest15(void)
2917 {
2920 
2921  int result = 0;
2922 
2923  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2924  "80",
2925  ALPROTO_HTTP,
2926  5, 8,
2927  STREAM_TOSERVER,
2928  ProbingParserDummyForTesting, NULL);
2929  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2930  "80",
2931  ALPROTO_SMB,
2932  5, 6,
2933  STREAM_TOSERVER,
2934  ProbingParserDummyForTesting, NULL);
2935  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2936  "80",
2937  ALPROTO_FTP,
2938  7, 10,
2939  STREAM_TOSERVER,
2940  ProbingParserDummyForTesting, NULL);
2941 
2942  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2943  "81",
2945  9, 10,
2946  STREAM_TOSERVER,
2947  ProbingParserDummyForTesting, NULL);
2948  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2949  "81",
2950  ALPROTO_FTP,
2951  7, 15,
2952  STREAM_TOSERVER,
2953  ProbingParserDummyForTesting, NULL);
2954  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2955  "0",
2956  ALPROTO_SMTP,
2957  12, 0,
2958  STREAM_TOSERVER,
2959  ProbingParserDummyForTesting, NULL);
2960  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2961  "0",
2962  ALPROTO_TLS,
2963  12, 18,
2964  STREAM_TOSERVER,
2965  ProbingParserDummyForTesting, NULL);
2966 
2967  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2968  "85",
2970  9, 10,
2971  STREAM_TOSERVER,
2972  ProbingParserDummyForTesting, NULL);
2973  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2974  "85",
2975  ALPROTO_FTP,
2976  7, 15,
2977  STREAM_TOSERVER,
2978  ProbingParserDummyForTesting, NULL);
2979  result = 1;
2980 
2981  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
2982  "85",
2983  ALPROTO_IMAP,
2984  12, 23,
2985  STREAM_TOSERVER,
2986  ProbingParserDummyForTesting, NULL);
2987 
2988  /* toclient */
2989  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2990  "0",
2992  12, 23,
2994  ProbingParserDummyForTesting, NULL);
2995  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2996  "0",
2997  ALPROTO_IRC,
2998  12, 14,
3000  ProbingParserDummyForTesting, NULL);
3001 
3002  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3003  "85",
3005  9, 10,
3007  ProbingParserDummyForTesting, NULL);
3008  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3009  "81",
3010  ALPROTO_FTP,
3011  7, 15,
3013  ProbingParserDummyForTesting, NULL);
3014  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3015  "0",
3016  ALPROTO_TLS,
3017  12, 18,
3019  ProbingParserDummyForTesting, NULL);
3020  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3021  "80",
3022  ALPROTO_HTTP,
3023  5, 8,
3025  ProbingParserDummyForTesting, NULL);
3026  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3027  "81",
3029  9, 10,
3031  ProbingParserDummyForTesting, NULL);
3032  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3033  "90",
3034  ALPROTO_FTP,
3035  7, 15,
3037  ProbingParserDummyForTesting, NULL);
3038  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3039  "80",
3040  ALPROTO_SMB,
3041  5, 6,
3043  ProbingParserDummyForTesting, NULL);
3044  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
3045  "85",
3046  ALPROTO_IMAP,
3047  12, 23,
3049  ProbingParserDummyForTesting, NULL);
3050  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3051  "0",
3052  ALPROTO_SMTP,
3053  12, 17,
3055  ProbingParserDummyForTesting, NULL);
3056  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
3057  "80",
3058  ALPROTO_FTP,
3059  7, 10,
3061  ProbingParserDummyForTesting, NULL);
3062 
3063  AppLayerProtoDetectPPTestDataElement element_ts_80[] = {
3064  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3065  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3066  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3067  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3068  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3069  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3070  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3071  };
3072  AppLayerProtoDetectPPTestDataElement element_tc_80[] = {
3073  { "http", ALPROTO_HTTP, 80, 1 << ALPROTO_HTTP, 5, 8 },
3074  { "smb", ALPROTO_SMB, 80, 1 << ALPROTO_SMB, 5, 6 },
3075  { "ftp", ALPROTO_FTP, 80, 1 << ALPROTO_FTP, 7, 10 },
3076  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3077  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3078  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3079  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3080  };
3081 
3082  AppLayerProtoDetectPPTestDataElement element_ts_81[] = {
3083  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3084  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3085  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3086  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3087  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3088  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3089  };
3090  AppLayerProtoDetectPPTestDataElement element_tc_81[] = {
3091  { "ftp", ALPROTO_FTP, 81, 1 << ALPROTO_FTP, 7, 15 },
3092  { "dcerpc", ALPROTO_DCERPC, 81, 1 << ALPROTO_DCERPC, 9, 10 },
3093  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3094  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3095  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3096  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3097  };
3098 
3099  AppLayerProtoDetectPPTestDataElement element_ts_85[] = {
3100  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3101  { "ftp", ALPROTO_FTP, 85, 1 << ALPROTO_FTP, 7, 15 },
3102  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3103  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3104  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3105  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3106  };
3107  AppLayerProtoDetectPPTestDataElement element_tc_85[] = {
3108  { "dcerpc", ALPROTO_DCERPC, 85, 1 << ALPROTO_DCERPC, 9, 10 },
3109  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3110  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3111  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3112  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3113  };
3114 
3115  AppLayerProtoDetectPPTestDataElement element_ts_90[] = {
3116  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3117  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3118  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3119  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3120  };
3121  AppLayerProtoDetectPPTestDataElement element_tc_90[] = {
3122  { "ftp", ALPROTO_FTP, 90, 1 << ALPROTO_FTP, 7, 15 },
3123  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3124  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3125  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3126  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3127  };
3128 
3129  AppLayerProtoDetectPPTestDataElement element_ts_0[] = {
3130  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 0 },
3131  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3132  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 25 },
3133  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3134  };
3135  AppLayerProtoDetectPPTestDataElement element_tc_0[] = {
3136  { "jabber", ALPROTO_JABBER, 0, 1 << ALPROTO_JABBER, 12, 23 },
3137  { "irc", ALPROTO_IRC, 0, 1 << ALPROTO_IRC, 12, 14 },
3138  { "tls", ALPROTO_TLS, 0, 1 << ALPROTO_TLS, 12, 18 },
3139  { "smtp", ALPROTO_SMTP, 0, 1 << ALPROTO_SMTP, 12, 17 }
3140  };
3141 
3142 
3143  AppLayerProtoDetectPPTestDataElement element_ts_85_udp[] = {
3144  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3145  };
3146  AppLayerProtoDetectPPTestDataElement element_tc_85_udp[] = {
3147  { "imap", ALPROTO_IMAP, 85, 1 << ALPROTO_IMAP, 12, 23 },
3148  };
3149 
3150  AppLayerProtoDetectPPTestDataPort ports_tcp[] = {
3151  { 80,
3152  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3153  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3154  ((1 << ALPROTO_HTTP) | (1 << ALPROTO_SMB) | (1 << ALPROTO_FTP) |
3155  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3156  23,
3157  element_ts_80, element_tc_80,
3158  sizeof(element_ts_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3159  sizeof(element_tc_80) / sizeof(AppLayerProtoDetectPPTestDataElement),
3160  },
3161  { 81,
3162  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3163  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3164  ((1 << ALPROTO_FTP) | (1 << ALPROTO_DCERPC) |
3165  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3166  23,
3167  element_ts_81, element_tc_81,
3168  sizeof(element_ts_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3169  sizeof(element_tc_81) / sizeof(AppLayerProtoDetectPPTestDataElement),
3170  },
3171  { 85,
3172  ((1 << ALPROTO_DCERPC) | (1 << ALPROTO_FTP) |
3173  (1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3174  ((1 << ALPROTO_DCERPC) |
3175  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3176  23,
3177  element_ts_85, element_tc_85,
3178  sizeof(element_ts_85) / sizeof(AppLayerProtoDetectPPTestDataElement),
3179  sizeof(element_tc_85) / sizeof(AppLayerProtoDetectPPTestDataElement)
3180  },
3181  { 90,
3182  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3183  ((1 << ALPROTO_FTP) |
3184  (1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3185  23,
3186  element_ts_90, element_tc_90,
3187  sizeof(element_ts_90) / sizeof(AppLayerProtoDetectPPTestDataElement),
3188  sizeof(element_tc_90) / sizeof(AppLayerProtoDetectPPTestDataElement)
3189  },
3190  { 0,
3191  ((1 << ALPROTO_SMTP) | (1 << ALPROTO_TLS) | (1 << ALPROTO_IRC) | (1 << ALPROTO_JABBER)),
3192  ((1 << ALPROTO_JABBER) | (1 << ALPROTO_IRC) | (1 << ALPROTO_TLS) | (1 << ALPROTO_SMTP)),
3193  23,
3194  element_ts_0, element_tc_0,
3195  sizeof(element_ts_0) / sizeof(AppLayerProtoDetectPPTestDataElement),
3196  sizeof(element_tc_0) / sizeof(AppLayerProtoDetectPPTestDataElement)
3197  }
3198  };
3199 
3200  AppLayerProtoDetectPPTestDataPort ports_udp[] = {
3201  { 85,
3202  (1 << ALPROTO_IMAP),
3203  (1 << ALPROTO_IMAP),
3204  23,
3205  element_ts_85_udp, element_tc_85_udp,
3206  sizeof(element_ts_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3207  sizeof(element_tc_85_udp) / sizeof(AppLayerProtoDetectPPTestDataElement),
3208  },
3209  };
3210 
3212  { IPPROTO_TCP,
3213  ports_tcp,
3214  sizeof(ports_tcp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3215  },
3216  { IPPROTO_UDP,
3217  ports_udp,
3218  sizeof(ports_udp) / sizeof(AppLayerProtoDetectPPTestDataPort),
3219  },
3220  };
3221 
3222 
3223  if (AppLayerProtoDetectPPTestData(alpd_ctx.ctx_pp, ip_proto,
3224  sizeof(ip_proto) / sizeof(AppLayerProtoDetectPPTestDataIPProto)) == 0) {
3225  goto end;
3226  }
3227  result = 1;
3228 
3229  end:
3232  return result;
3233 }
3234 
3235 
3236 /** \test test if the engine detect the proto and match with it */
3237 static int AppLayerProtoDetectTest16(void)
3238 {
3239  int result = 0;
3240  Flow *f = NULL;
3241  HtpState *http_state = NULL;
3242  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3243  "User-Agent: Mozilla/1.0\r\n"
3244  "Cookie: hellocatch\r\n\r\n";
3245  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3246  TcpSession ssn;
3247  Packet *p = NULL;
3248  Signature *s = NULL;
3249  ThreadVars tv;
3250  DetectEngineThreadCtx *det_ctx = NULL;
3251  DetectEngineCtx *de_ctx = NULL;
3253 
3254  memset(&tv, 0, sizeof(ThreadVars));
3255  memset(&ssn, 0, sizeof(TcpSession));
3256 
3257  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3258  if (p == NULL) {
3259  printf("packet setup failed: ");
3260  goto end;
3261  }
3262 
3263  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3264  if (f == NULL) {
3265  printf("flow setup failed: ");
3266  goto end;
3267  }
3268  f->protoctx = &ssn;
3269  f->proto = IPPROTO_TCP;
3270  p->flow = f;
3271 
3275 
3276  f->alproto = ALPROTO_HTTP;
3277 
3279 
3280  de_ctx = DetectEngineCtxInit();
3281  if (de_ctx == NULL) {
3282  goto end;
3283  }
3284  de_ctx->flags |= DE_QUIET;
3285 
3286  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any any -> any any "
3287  "(msg:\"Test content option\"; "
3288  "sid:1;)");
3289  if (s == NULL) {
3290  goto end;
3291  }
3292 
3293  SigGroupBuild(de_ctx);
3294  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3295 
3296  FLOWLOCK_WRLOCK(f);
3297  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3298  STREAM_TOSERVER, http_buf1, http_buf1_len);
3299  if (r != 0) {
3300  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3301  FLOWLOCK_UNLOCK(f);
3302  goto end;
3303  }
3304  FLOWLOCK_UNLOCK(f);
3305 
3306  http_state = f->alstate;
3307  if (http_state == NULL) {
3308  printf("no http state: ");
3309  goto end;
3310  }
3311 
3312  /* do detect */
3313  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3314 
3315  if (!PacketAlertCheck(p, 1)) {
3316  printf("sig 1 didn't alert, but it should: ");
3317  goto end;
3318  }
3319  result = 1;
3320  end:
3321  if (alp_tctx != NULL)
3322  AppLayerParserThreadCtxFree(alp_tctx);
3323  if (det_ctx != NULL)
3324  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3325  if (de_ctx != NULL)
3326  SigGroupCleanup(de_ctx);
3327  if (de_ctx != NULL)
3328  DetectEngineCtxFree(de_ctx);
3329 
3331 
3332  UTHFreePackets(&p, 1);
3333  UTHFreeFlow(f);
3334  return result;
3335 }
3336 
3337 /** \test test if the engine detect the proto on a non standar port
3338  * and match with it */
3339 static int AppLayerProtoDetectTest17(void)
3340 {
3341  int result = 0;
3342  Flow *f = NULL;
3343  HtpState *http_state = NULL;
3344  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3345  "User-Agent: Mozilla/1.0\r\n"
3346  "Cookie: hellocatch\r\n\r\n";
3347  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3348  TcpSession ssn;
3349  Packet *p = NULL;
3350  Signature *s = NULL;
3351  ThreadVars tv;
3352  DetectEngineThreadCtx *det_ctx = NULL;
3353  DetectEngineCtx *de_ctx = NULL;
3355 
3356  memset(&tv, 0, sizeof(ThreadVars));
3357  memset(&ssn, 0, sizeof(TcpSession));
3358 
3359  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3360 
3361  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3362  if (f == NULL)
3363  goto end;
3364  f->protoctx = &ssn;
3365  f->proto = IPPROTO_TCP;
3366  p->flow = f;
3370  f->alproto = ALPROTO_HTTP;
3371 
3373 
3374  de_ctx = DetectEngineCtxInit();
3375  if (de_ctx == NULL) {
3376  goto end;
3377  }
3378  de_ctx->flags |= DE_QUIET;
3379 
3380  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3381  "(msg:\"http over non standar port\"; "
3382  "sid:1;)");
3383  if (s == NULL) {
3384  goto end;
3385  }
3386 
3387  SigGroupBuild(de_ctx);
3388  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3389 
3390  FLOWLOCK_WRLOCK(f);
3391  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3392  STREAM_TOSERVER, http_buf1, http_buf1_len);
3393  if (r != 0) {
3394  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3395  FLOWLOCK_UNLOCK(f);
3396  goto end;
3397  }
3398  FLOWLOCK_UNLOCK(f);
3399 
3400  http_state = f->alstate;
3401  if (http_state == NULL) {
3402  printf("no http state: ");
3403  goto end;
3404  }
3405 
3406  /* do detect */
3407  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3408 
3409  if (!PacketAlertCheck(p, 1)) {
3410  printf("sig 1 didn't alert, but it should: ");
3411  goto end;
3412  }
3413 
3414  result = 1;
3415 
3416  end:
3417  if (alp_tctx != NULL)
3418  AppLayerParserThreadCtxFree(alp_tctx);
3419  if (det_ctx != NULL)
3420  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3421  if (de_ctx != NULL)
3422  SigGroupCleanup(de_ctx);
3423  if (de_ctx != NULL)
3424  DetectEngineCtxFree(de_ctx);
3425 
3427 
3428  UTHFreePackets(&p, 1);
3429  UTHFreeFlow(f);
3430  return result;
3431 }
3432 
3433 /** \test test if the engine detect the proto and doesn't match
3434  * because the sig expects another proto (ex ftp)*/
3435 static int AppLayerProtoDetectTest18(void)
3436 {
3437  int result = 0;
3438  Flow *f = NULL;
3439  HtpState *http_state = NULL;
3440  uint8_t http_buf1[] = "POST /one HTTP/1.0\r\n"
3441  "User-Agent: Mozilla/1.0\r\n"
3442  "Cookie: hellocatch\r\n\r\n";
3443  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3444  TcpSession ssn;
3445  Packet *p = NULL;
3446  Signature *s = NULL;
3447  ThreadVars tv;
3448  DetectEngineThreadCtx *det_ctx = NULL;
3449  DetectEngineCtx *de_ctx = NULL;
3451 
3452  memset(&tv, 0, sizeof(ThreadVars));
3453  memset(&ssn, 0, sizeof(TcpSession));
3454 
3455  p = UTHBuildPacket(http_buf1, http_buf1_len, IPPROTO_TCP);
3456 
3457  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3458  if (f == NULL)
3459  goto end;
3460  f->protoctx = &ssn;
3461  f->proto = IPPROTO_TCP;
3462  p->flow = f;
3466  f->alproto = ALPROTO_HTTP;
3467 
3469 
3470  de_ctx = DetectEngineCtxInit();
3471  if (de_ctx == NULL) {
3472  goto end;
3473  }
3474  de_ctx->flags |= DE_QUIET;
3475 
3476  s = de_ctx->sig_list = SigInit(de_ctx, "alert ftp any any -> any any "
3477  "(msg:\"Test content option\"; "
3478  "sid:1;)");
3479  if (s == NULL) {
3480  goto end;
3481  }
3482 
3483  SigGroupBuild(de_ctx);
3484  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3485 
3486  FLOWLOCK_WRLOCK(f);
3487  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
3488  STREAM_TOSERVER, http_buf1, http_buf1_len);
3489  if (r != 0) {
3490  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3491  FLOWLOCK_UNLOCK(f);
3492  goto end;
3493  }
3494  FLOWLOCK_UNLOCK(f);
3495 
3496  http_state = f->alstate;
3497  if (http_state == NULL) {
3498  printf("no http state: ");
3499  goto end;
3500  }
3501 
3502  /* do detect */
3503  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3504 
3505  if (PacketAlertCheck(p, 1)) {
3506  printf("sig 1 alerted, but it should not (it's not ftp): ");
3507  goto end;
3508  }
3509 
3510  result = 1;
3511  end:
3512  if (alp_tctx != NULL)
3513  AppLayerParserThreadCtxFree(alp_tctx);
3514  if (det_ctx != NULL)
3515  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3516  if (de_ctx != NULL)
3517  SigGroupCleanup(de_ctx);
3518  if (de_ctx != NULL)
3519  DetectEngineCtxFree(de_ctx);
3520 
3522 
3523  UTHFreePackets(&p, 1);
3524  UTHFreeFlow(f);
3525  return result;
3526 }
3527 
3528 /** \test test if the engine detect the proto and doesn't match
3529  * because the packet has another proto (ex ftp) */
3530 static int AppLayerProtoDetectTest19(void)
3531 {
3532  int result = 0;
3533  Flow *f = NULL;
3534  uint8_t http_buf1[] = "MPUT one\r\n";
3535  uint32_t http_buf1_len = sizeof(http_buf1) - 1;
3536  TcpSession ssn;
3537  Packet *p = NULL;
3538  Signature *s = NULL;
3539  ThreadVars tv;
3540  DetectEngineThreadCtx *det_ctx = NULL;
3541  DetectEngineCtx *de_ctx = NULL;
3543 
3544  memset(&tv, 0, sizeof(ThreadVars));
3545  memset(&ssn, 0, sizeof(TcpSession));
3546 
3547  p = UTHBuildPacketSrcDstPorts(http_buf1, http_buf1_len, IPPROTO_TCP, 12345, 88);
3548 
3549  f = UTHBuildFlow(AF_INET, "1.1.1.1", "2.2.2.2", 1024, 80);
3550  if (f == NULL)
3551  goto end;
3552  f->protoctx = &ssn;
3553  f->proto = IPPROTO_TCP;
3554  p->flow = f;
3558  f->alproto = ALPROTO_FTP;
3559 
3561 
3562  de_ctx = DetectEngineCtxInit();
3563  if (de_ctx == NULL) {
3564  goto end;
3565  }
3566  de_ctx->flags |= DE_QUIET;
3567 
3568  s = de_ctx->sig_list = SigInit(de_ctx, "alert http any !80 -> any any "
3569  "(msg:\"http over non standar port\"; "
3570  "sid:1;)");
3571  if (s == NULL) {
3572  goto end;
3573  }
3574 
3575  SigGroupBuild(de_ctx);
3576  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
3577 
3578  FLOWLOCK_WRLOCK(f);
3579  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_FTP,
3580  STREAM_TOSERVER, http_buf1, http_buf1_len);
3581  if (r != 0) {
3582  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
3583  FLOWLOCK_UNLOCK(f);
3584  goto end;
3585  }
3586  FLOWLOCK_UNLOCK(f);
3587 
3588  /* do detect */
3589  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
3590 
3591  if (PacketAlertCheck(p, 1)) {
3592  printf("sig 1 alerted, but it should not (it's ftp): ");
3593  goto end;
3594  }
3595 
3596  result = 1;
3597 
3598  end:
3599  if (alp_tctx != NULL)
3600  AppLayerParserThreadCtxFree(alp_tctx);
3601  if (det_ctx != NULL)
3602  DetectEngineThreadCtxDeinit(&tv, det_ctx);
3603  if (de_ctx != NULL)
3604  SigGroupCleanup(de_ctx);
3605  if (de_ctx != NULL)
3606  DetectEngineCtxFree(de_ctx);
3607 
3609  UTHFreePackets(&p, 1);
3610  UTHFreeFlow(f);
3611  return result;
3612 }
3613 
3615 {
3616  SCEnter();
3617 
3618  UtRegisterTest("AppLayerProtoDetectTest01", AppLayerProtoDetectTest01);
3619  UtRegisterTest("AppLayerProtoDetectTest02", AppLayerProtoDetectTest02);
3620  UtRegisterTest("AppLayerProtoDetectTest03", AppLayerProtoDetectTest03);
3621  UtRegisterTest("AppLayerProtoDetectTest04", AppLayerProtoDetectTest04);
3622  UtRegisterTest("AppLayerProtoDetectTest05", AppLayerProtoDetectTest05);
3623  UtRegisterTest("AppLayerProtoDetectTest06", AppLayerProtoDetectTest06);
3624  UtRegisterTest("AppLayerProtoDetectTest07", AppLayerProtoDetectTest07);
3625  UtRegisterTest("AppLayerProtoDetectTest08", AppLayerProtoDetectTest08);
3626  UtRegisterTest("AppLayerProtoDetectTest09", AppLayerProtoDetectTest09);
3627  UtRegisterTest("AppLayerProtoDetectTest10", AppLayerProtoDetectTest10);
3628  UtRegisterTest("AppLayerProtoDetectTest11", AppLayerProtoDetectTest11);
3629  UtRegisterTest("AppLayerProtoDetectTest12", AppLayerProtoDetectTest12);
3630  UtRegisterTest("AppLayerProtoDetectTest13", AppLayerProtoDetectTest13);
3631  UtRegisterTest("AppLayerProtoDetectTest14", AppLayerProtoDetectTest14);
3632  UtRegisterTest("AppLayerProtoDetectTest15", AppLayerProtoDetectTest15);
3633  UtRegisterTest("AppLayerProtoDetectTest16", AppLayerProtoDetectTest16);
3634  UtRegisterTest("AppLayerProtoDetectTest17", AppLayerProtoDetectTest17);
3635  UtRegisterTest("AppLayerProtoDetectTest18", AppLayerProtoDetectTest18);
3636  UtRegisterTest("AppLayerProtoDetectTest19", AppLayerProtoDetectTest19);
3637 
3638  SCReturn;
3639 }
3640 
3641 #endif /* UNITTESTS */
const char * AppLayerProtoDetectGetProtoName(AppProto alproto)
struct AppLayerProtoDetectProbingParser_ * next
AppProto alproto_expect
Definition: flow.h:413
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:406
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:343
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:242
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:729
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:202
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:239
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:495
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
#define FLOW_SET_PM_DONE(f, dir)
Definition: flow.h:251
#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:395
main detection engine ctx
Definition: detect.h:723
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:372
void * alstate
Definition: flow.h:433
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:405
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:257
#define FLOW_IS_PM_DONE(f, dir)
Definition: flow.h:247
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:724
uint16_t protodetect_dp
Definition: flow.h:381
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:140
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:1743
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:200
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:259
MpmThreadCtx mpm_tctx[FLOW_PROTO_DEFAULT][2]
AppLayerProtoDetectPMSignature ** map
#define FLOW_SET_PP_DONE(f, dir)
Definition: flow.h:252
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:371
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:248
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:253
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:255
#define FLOW_IS_PE_DONE(f, dir)
Definition: flow.h:249
#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:138
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:256
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:404
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:399
Flow data structure.
Definition: flow.h:324
#define SigIntId
#define PKT_STREAM_EST
Definition: decode.h:1090
Port structure for detection engine.
Definition: detect.h:196
AppLayerParserState * alparser
Definition: flow.h:432
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