suricata
detect-app-layer-protocol.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2026 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22  */
23 
24 #include "suricata-common.h"
25 #include "detect-engine.h"
26 #include "detect-engine-build.h"
29 #include "detect-parse.h"
31 #include "app-layer.h"
32 #include "app-layer-parser.h"
33 #include "app-layer-detect-proto.h"
34 #include "util-debug.h"
35 #include "util-unittest.h"
36 #include "util-unittest-helper.h"
37 
38 #ifdef UNITTESTS
39 static void DetectAppLayerProtocolRegisterTests(void);
40 #endif
41 
42 enum {
49 };
50 
51 static void DetectAppLayerProtocolFree(DetectEngineCtx *de_ctx, void *ptr);
52 
53 /** \internal
54  * \brief size in bytes of an alproto bitmask (g_alproto_max bits). */
55 static inline uint32_t AlprotoBitmaskSize(void)
56 {
57  return (uint32_t)((g_alproto_max + 7) / 8);
58 }
59 
60 static inline void AlprotoBitmaskSet(uint8_t *bm, AppProto a)
61 {
62  bm[a >> 3] |= (uint8_t)(1u << (a & 7));
63 }
64 
65 static inline bool AlprotoBitmaskTest(const uint8_t *bm, AppProto a)
66 {
67  return (bm[a >> 3] & (uint8_t)(1u << (a & 7))) != 0;
68 }
69 
70 /** \internal
71  * \brief Compare a configured value against a flow protocol under the rule's
72  * matching policy.
73  *
74  * By default the historical AppProtoEquals() equivalences apply (dns/doh2,
75  * http/http1/http2, dcerpc/smb, ...). With the `exact` option the match is a
76  * strict identity, with no equivalences and no http umbrella. Used to expand
77  * the match set at rule load and by the single-value prefilter comparator. */
78 static inline bool DetectAppLayerProtocolCompare(AppProto sigproto, AppProto alproto, bool exact)
79 {
80  return exact ? (sigproto == alproto) : AppProtoEquals(sigproto, alproto);
81 }
82 
83 /** \internal
84  * \brief Expand one configured value into the match bitmask: set a bit for
85  * every flow protocol that should match it. Done once at rule load so
86  * the per-packet match is a single bitmask test. */
87 static void DetectAppLayerProtocolExpand(uint8_t *bm, AppProto sigproto, bool exact)
88 {
89  for (AppProto a = 0; a < g_alproto_max; a++) {
90  if (DetectAppLayerProtocolCompare(sigproto, a, exact))
91  AlprotoBitmaskSet(bm, a);
92  }
93 }
94 
95 static int DetectAppLayerProtocolPacketMatch(
96  DetectEngineThreadCtx *det_ctx,
97  Packet *p, const Signature *s, const SigMatchCtx *ctx)
98 {
99  SCEnter();
100 
102 
103  /* if the sig is PD-only we only match when PD packet flags are set */
104  if (s->type == SIG_TYPE_PDONLY &&
106  SCLogDebug("packet %" PRIu64 ": flags not set", PcapPacketCntGet(p));
107  SCReturnInt(0);
108  }
109 
110  const Flow *f = p->flow;
111  if (f == NULL) {
112  SCLogDebug("packet %" PRIu64 ": no flow", PcapPacketCntGet(p));
113  SCReturnInt(0);
114  }
115 
116  /* Resolve the flow's alproto for the configured mode. */
117  AppProto resolved_alproto = ALPROTO_UNKNOWN;
118  switch (data->mode) {
120  if (p->flowflags & FLOW_PKT_TOSERVER) {
121  resolved_alproto = f->alproto_ts;
122  } else {
123  resolved_alproto = f->alproto_tc;
124  }
125  break;
126  case DETECT_ALPROTO_ORIG:
127  resolved_alproto = f->alproto_orig;
128  break;
130  resolved_alproto = f->alproto;
131  break;
133  resolved_alproto = f->alproto_ts;
134  break;
136  resolved_alproto = f->alproto_tc;
137  break;
139  /* Handled separately below against both directions. */
140  break;
141  }
142 
143  /* Negated rules never match when alproto is still unknown. */
144  if (data->negated) {
145  if (data->mode == DETECT_ALPROTO_EITHER) {
147  SCReturnInt(0);
148  }
149  } else {
150  if (resolved_alproto == ALPROTO_UNKNOWN) {
151  SCReturnInt(0);
152  }
153  }
154  }
155 
156  bool r = false;
157  if (data->mode == DETECT_ALPROTO_EITHER) {
158  r = AlprotoBitmaskTest(data->alprotos, f->alproto_ts) ||
159  AlprotoBitmaskTest(data->alprotos, f->alproto_tc);
160  } else {
161  r = AlprotoBitmaskTest(data->alprotos, resolved_alproto);
162  }
163 
164  /* XOR with negated for NOR semantics. */
165  r = r ^ data->negated;
166 
167  if (r) {
168  SCReturnInt(1);
169  }
170  SCReturnInt(0);
171 }
172 
173 #define MAX_ALPROTO_NAME 50
174 
175 /** \internal
176  * \brief Map a textual mode-qualifier token to its DETECT_ALPROTO_* value.
177  */
178 static int DetectAppLayerProtocolMapModeName(const char *name)
179 {
180  if (strcmp(name, "final") == 0)
181  return DETECT_ALPROTO_FINAL;
182  if (strcmp(name, "original") == 0)
183  return DETECT_ALPROTO_ORIG;
184  if (strcmp(name, "either") == 0)
185  return DETECT_ALPROTO_EITHER;
186  if (strcmp(name, "to_server") == 0)
188  if (strcmp(name, "to_client") == 0)
190  if (strcmp(name, "direction") == 0)
192  return -1;
193 }
194 
195 /** \brief Map a DETECT_ALPROTO_* mode value to its textual qualifier. */
196 const char *DetectAppLayerProtocolModeName(uint8_t mode)
197 {
198  switch (mode) {
200  return "final";
201  case DETECT_ALPROTO_ORIG:
202  return "original";
204  return "either";
206  return "to_server";
208  return "to_client";
210  default:
211  return "direction";
212  }
213 }
214 
215 /** \brief Fill out[] with the keyword's set protocol values.
216  * \retval number of values written (capped at max). */
218  const DetectAppLayerProtocolData *data, AppProto *out, uint16_t max)
219 {
220  uint16_t n = 0;
221  for (AppProto a = 0; a < g_alproto_max && n < max; a++) {
222  if (AlprotoBitmaskTest(data->alprotos, a))
223  out[n++] = a;
224  }
225  return n;
226 }
227 
228 /** \internal
229  * \brief Build a comma-separated list of supported app-layer protocol names.
230  */
231 static void DetectAppLayerProtocolBuildSupportedList(char *buf, size_t buflen)
232 {
233  if (buflen == 0)
234  return;
235  buf[0] = '\0';
236 
237  AppProto alprotos[g_alproto_max];
239 
240  size_t offset = 0;
241  for (AppProto a = 0; a < g_alproto_max; a++) {
242  if (alprotos[a] != 1)
243  continue;
244  const char *name = AppProtoToString(a);
245  if (name == NULL)
246  continue;
247  int w = snprintf(buf + offset, buflen - offset, "%s%s", (offset == 0) ? "" : ", ", name);
248  if (w < 0 || (size_t)w >= buflen - offset)
249  break; /* truncated; stop appending */
250  offset += (size_t)w;
251  }
252 }
253 
254 /** \internal
255  * \brief Resolve a single protocol token to its AppProto value.
256  * \retval 0 on success, -1 on error (logs the reason). */
257 static int DetectAppLayerProtocolResolveToken(
258  const char *token, const char *arg, bool negate, AppProto *out)
259 {
260  size_t tlen = strlen(token);
261  if (tlen == 0) {
262  SCLogError("app-layer-protocol keyword value \"%s\" contains an empty token", arg);
263  return -1;
264  }
265  if (tlen >= MAX_ALPROTO_NAME) {
266  SCLogError("app-layer-protocol keyword token \"%s\" in \"%s\" exceeds the "
267  "maximum token length of %d characters",
268  token, arg, MAX_ALPROTO_NAME - 1);
269  return -1;
270  }
271  if (strcmp(token, "failed") == 0) {
272  *out = ALPROTO_FAILED;
273  return 0;
274  }
275  if (strcmp(token, "unknown") == 0) {
276  if (negate) {
277  SCLogError("app-layer-protocol keyword can't use negation with protocol 'unknown'");
278  return -1;
279  }
280  *out = ALPROTO_UNKNOWN;
281  return 0;
282  }
283  AppProto ap = AppLayerGetProtoByName(token);
284  if (ap == ALPROTO_UNKNOWN) {
285  char supported[1024];
286  DetectAppLayerProtocolBuildSupportedList(supported, sizeof(supported));
287  SCLogError("app-layer-protocol keyword supplied with unknown protocol "
288  "\"%s\" in \"%s\"; supported protocols: %s",
289  token, arg, supported);
290  return -1;
291  }
292  *out = ap;
293  return 0;
294 }
295 
296 static DetectAppLayerProtocolData *DetectAppLayerProtocolParse(const char *arg, bool negate)
297 {
298  if (arg == NULL) {
299  SCLogError("app-layer-protocol keyword requires a value");
300  return NULL;
301  }
302 
303  /* Total-length validation. The limit bounds the on-stack copy below
304  * (buf[1025]) and is far larger than any realistic protocol value list. */
305  size_t arglen = strlen(arg);
306  if (arglen > 1024) {
307  SCLogError("app-layer-protocol keyword argument too long (\"%s\"): maximum "
308  "supported length is 1024 characters",
309  arg);
310  return NULL;
311  }
312  if (arglen == 0) {
313  SCLogError("app-layer-protocol keyword value is empty (an empty value list "
314  "is not permitted)");
315  return NULL;
316  }
317 
318  char buf[1025];
319  strlcpy(buf, arg, sizeof(buf));
320 
321  /* Split the protocol list from the trailing comma-separated qualifiers.
322  * The list itself is pipe-separated; each qualifier is a direction mode
323  * (at most one) or the `exact` option, in any order. */
324  uint8_t mode = DETECT_ALPROTO_DIRECTION;
325  bool exact = false;
326  char *qualifiers = strchr(buf, ',');
327  if (qualifiers != NULL) {
328  *qualifiers = '\0';
329  qualifiers++;
330  bool mode_set = false;
331  char *q = qualifiers;
332  while (q != NULL && *q != '\0') {
333  char *next = strchr(q, ',');
334  if (next != NULL)
335  *next++ = '\0';
336  if (strcmp(q, "exact") == 0) {
337  exact = true;
338  } else {
339  int m = DetectAppLayerProtocolMapModeName(q);
340  if (m < 0) {
341  SCLogError("app-layer-protocol keyword supplied with unknown "
342  "qualifier \"%s\" in \"%s\"",
343  q, arg);
344  return NULL;
345  }
346  if (mode_set) {
347  SCLogError("app-layer-protocol keyword supplied with multiple "
348  "mode qualifiers in \"%s\"",
349  arg);
350  return NULL;
351  }
352  mode = (uint8_t)m;
353  mode_set = true;
354  }
355  q = next;
356  }
357  }
358 
359  DetectAppLayerProtocolData *data = SCCalloc(1, sizeof(*data));
360  if (unlikely(data == NULL))
361  return NULL;
362  data->alprotos = SCCalloc(1, AlprotoBitmaskSize());
363  if (unlikely(data->alprotos == NULL)) {
364  SCFree(data);
365  return NULL;
366  }
367  data->negated = negate;
368  data->mode = mode;
369  data->exact = exact;
370  data->alproto = ALPROTO_UNKNOWN;
371 
372  /* Tokenize the protocol list on '|' and expand each value into the
373  * effective match set under the chosen policy, so the per-packet match is
374  * a single bitmask test. */
375  int value_count = 0;
376  char *cur = buf;
377  while (1) {
378  char *pipe = strchr(cur, '|');
379  if (pipe != NULL)
380  *pipe = '\0';
381 
382  AppProto value;
383  if (DetectAppLayerProtocolResolveToken(cur, arg, negate, &value) < 0)
384  goto error;
385 
386  /* The generic ALPROTO_HTTP is never a flow's classified protocol, so
387  * an exact http match can never fire; steer users to http1/http2. */
388  if (exact && value == ALPROTO_HTTP) {
389  SCLogError("app-layer-protocol keyword: 'http' with 'exact' never "
390  "matches (flows are classified as http1/http2); use "
391  "http1 or http2");
392  goto error;
393  }
394 
395  if (value_count == 0)
396  data->alproto = value;
397  DetectAppLayerProtocolExpand(data->alprotos, value, exact);
398  value_count++;
399 
400  if (pipe == NULL)
401  break;
402  cur = pipe + 1;
403  }
404 
405  data->is_list = (value_count > 1);
406  if (data->is_list)
407  data->alproto = ALPROTO_UNKNOWN; /* lists are not prefilterable: no single-value key */
408 
409  return data;
410 
411 error:
412  DetectAppLayerProtocolFree(NULL, data);
413  return NULL;
414 }
415 
416 /**
417  * \brief Check whether two app-layer-protocol SigMatches conflict.
418  */
419 static bool DetectAppLayerProtocolsConflict(
421 {
422  /* Different modes never conflict. */
423  if (us->mode != them->mode)
424  return false;
425 
426  /* Both negated under the same mode: only a conflict when the value sets
427  * intersect. Identical or overlapping negated lists are redundant, while
428  * disjoint negated lists (e.g. !http; !dns;) are a valid NOR combination. */
429  if (us->negated && them->negated) {
430  for (AppProto a = 0; a < g_alproto_max; a++) {
431  if (AlprotoBitmaskTest(us->alprotos, a) && AlprotoBitmaskTest(them->alprotos, a)) {
432  SCLogError("conflicting app-layer-protocol rules: "
433  "duplicate or overlapping negated entries under the same mode");
434  return true;
435  }
436  }
437  return false;
438  }
439 
440  /* Two non-negated under the same mode: always conflict. */
441  if (!us->negated && !them->negated) {
442  SCLogError("conflicting app-layer-protocol rules: "
443  "multiple non-negated entries under the same mode");
444  return true;
445  }
446 
447  /* Mixed negation under the same mode: conflict. Collect the intersecting
448  * values for the error message. */
449  char conflict_buf[512];
450  size_t buf_offset = 0;
451  bool has_intersection = false;
452 
453  for (AppProto a = 0; a < g_alproto_max; a++) {
454  if (!AlprotoBitmaskTest(us->alprotos, a) || !AlprotoBitmaskTest(them->alprotos, a))
455  continue;
456  has_intersection = true;
457  const char *name = AppProtoToString(a);
458  if (name == NULL)
459  name = "unknown";
460  if (buf_offset > 0 && buf_offset < sizeof(conflict_buf) - 2) {
461  conflict_buf[buf_offset++] = ',';
462  conflict_buf[buf_offset++] = ' ';
463  }
464  size_t name_len = strlen(name);
465  if (buf_offset + name_len < sizeof(conflict_buf) - 1) {
466  memcpy(conflict_buf + buf_offset, name, name_len);
467  buf_offset += name_len;
468  }
469  }
470  conflict_buf[buf_offset] = '\0';
471 
472  if (has_intersection) {
473  SCLogError("conflicting app-layer-protocol rules: "
474  "can't mix positive match with negated match under the same "
475  "mode; intersecting protocol value(s): %s",
476  conflict_buf);
477  } else {
478  SCLogError("conflicting app-layer-protocol rules: "
479  "can't mix positive app-layer-protocol match with negated "
480  "match or match for 'failed'");
481  }
482  return true;
483 }
484 
485 static int DetectAppLayerProtocolSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
486 {
487  DetectAppLayerProtocolData *data = NULL;
488 
489  /* Early rejection: rule already bound to a protocol. */
490  if (s->alproto != ALPROTO_UNKNOWN) {
491  SCLogError("Either we already "
492  "have the rule match on an app layer protocol set through "
493  "other keywords that match on this protocol, or have "
494  "already seen a non-negated app-layer-protocol.");
495  goto error;
496  }
497 
498  data = DetectAppLayerProtocolParse(arg, s->init_data->negated);
499  if (data == NULL)
500  goto error;
501 
503  for (; tsm != NULL; tsm = tsm->next) {
504  if (tsm->type == DETECT_APP_LAYER_PROTOCOL) {
505  const DetectAppLayerProtocolData *them = (const DetectAppLayerProtocolData *)tsm->ctx;
506 
507  if (DetectAppLayerProtocolsConflict(data, them)) {
508  SCLogError("conflicting app-layer-protocol options detected "
509  "(see preceding error for details).");
510  goto error;
511  }
512  }
513  }
514 
516  DETECT_SM_LIST_MATCH) == NULL) {
517  goto error;
518  }
519  return 0;
520 
521 error:
522  DetectAppLayerProtocolFree(de_ctx, data);
523  return -1;
524 }
525 
526 static void DetectAppLayerProtocolFree(DetectEngineCtx *de_ctx, void *ptr)
527 {
529  if (data == NULL)
530  return;
531  if (data->alprotos != NULL)
532  SCFree(data->alprotos);
533  SCFree(data);
534 }
535 
536 /** \internal
537  * \brief prefilter function for protocol detect matching
538  */
539 static void PrefilterPacketAppProtoMatch(
540  DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
541 {
542  const PrefilterPacketHeaderCtx *ctx = pectx;
543 
544  if (!PrefilterPacketHeaderExtraMatch(ctx, p)) {
545  SCLogDebug("packet %" PRIu64 ": extra match failed", PcapPacketCntGet(p));
546  SCReturn;
547  }
548 
549  if (p->flow == NULL) {
550  SCLogDebug("packet %" PRIu64 ": no flow, no alproto", PcapPacketCntGet(p));
551  SCReturn;
552  }
553 
555  SCLogDebug("packet %" PRIu64 ": flags not set", PcapPacketCntGet(p));
556  SCReturn;
557  }
558 
559  Flow *f = p->flow;
560  AppProto alproto = ALPROTO_UNKNOWN;
561  bool negated = (bool)ctx->v1.u8[2];
562  bool exact = (bool)ctx->v1.u8[4];
563  switch (ctx->v1.u8[3]) {
565  if (p->flowflags & FLOW_PKT_TOSERVER) {
566  alproto = f->alproto_ts;
567  } else {
568  alproto = f->alproto_tc;
569  }
570  break;
571  case DETECT_ALPROTO_ORIG:
572  alproto = f->alproto_orig;
573  break;
575  alproto = f->alproto;
576  break;
578  alproto = f->alproto_ts;
579  break;
581  alproto = f->alproto_tc;
582  break;
584  // check if either protocol toclient or toserver matches
585  // the one in the signature ctx
586  if (negated) {
587  if (f->alproto_tc != ALPROTO_UNKNOWN &&
588  !DetectAppLayerProtocolCompare(ctx->v1.u16[0], f->alproto_tc, exact)) {
589  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
590  } else if (f->alproto_ts != ALPROTO_UNKNOWN &&
591  !DetectAppLayerProtocolCompare(ctx->v1.u16[0], f->alproto_ts, exact)) {
592  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
593  }
594  } else {
595  if (DetectAppLayerProtocolCompare(ctx->v1.u16[0], f->alproto_tc, exact) ||
596  DetectAppLayerProtocolCompare(ctx->v1.u16[0], f->alproto_ts, exact)) {
597  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
598  }
599  }
600  // We return right away to avoid calling PrefilterAddSids again
601  return;
602  }
603 
604  if (negated) {
605  if (alproto != ALPROTO_UNKNOWN) {
606  if (!DetectAppLayerProtocolCompare(ctx->v1.u16[0], alproto, exact)) {
607  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
608  }
609  }
610  } else {
611  if (DetectAppLayerProtocolCompare(ctx->v1.u16[0], alproto, exact)) {
612  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
613  }
614  }
615 }
616 
617 static void
618 PrefilterPacketAppProtoSet(PrefilterPacketHeaderValue *v, void *smctx)
619 {
620  const DetectAppLayerProtocolData *a = smctx;
621  /* Only single-value rules are prefilterable; alproto is that value. */
622  v->u16[0] = a->alproto;
623  v->u8[2] = (uint8_t)a->negated;
624  v->u8[3] = a->mode;
625  v->u8[4] = (uint8_t)a->exact;
626 }
627 
628 static bool
629 PrefilterPacketAppProtoCompare(PrefilterPacketHeaderValue v, void *smctx)
630 {
631  const DetectAppLayerProtocolData *a = smctx;
632  return v.u16[0] == a->alproto && v.u8[2] == (uint8_t)a->negated && v.u8[3] == a->mode &&
633  v.u8[4] == (uint8_t)a->exact;
634 }
635 
636 static int PrefilterSetupAppProto(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
637 {
639  PrefilterPacketAppProtoSet, PrefilterPacketAppProtoCompare,
640  PrefilterPacketAppProtoMatch);
641 }
642 
643 static bool PrefilterAppProtoIsPrefilterable(const Signature *s)
644 {
645  if (s->type != SIG_TYPE_PDONLY) {
646  return false;
647  }
648 
649  /* Multi-value rules cannot be prefiltered (single-valued bucket key). */
650  const SigMatch *sm;
651  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH]; sm != NULL; sm = sm->next) {
652  if (sm->type == DETECT_APP_LAYER_PROTOCOL) {
653  const DetectAppLayerProtocolData *data = (const DetectAppLayerProtocolData *)sm->ctx;
654  if (data->is_list) {
655  return false;
656  }
657  break;
658  }
659  }
660  return true;
661 }
662 
664 {
665  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].name = "app-layer-protocol";
666  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].desc = "match on the detected app-layer protocol";
667  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].url = "/rules/app-layer.html#app-layer-protocol";
668  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Match = DetectAppLayerProtocolPacketMatch;
669  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Setup = DetectAppLayerProtocolSetup;
670  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Free = DetectAppLayerProtocolFree;
671 #ifdef UNITTESTS
672  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].RegisterTests = DetectAppLayerProtocolRegisterTests;
673 #endif
676 
677  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SetupPrefilter = PrefilterSetupAppProto;
678  sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SupportsPrefilter = PrefilterAppProtoIsPrefilterable;
679 }
680 
681 /**********************************Unittests***********************************/
682 
683 #ifdef UNITTESTS
684 
685 static int DetectAppLayerProtocolTest01(void)
686 {
687  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", false);
688  FAIL_IF_NULL(data);
689  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
690  FAIL_IF(data->negated != 0);
691  DetectAppLayerProtocolFree(NULL, data);
692  PASS;
693 }
694 
695 static int DetectAppLayerProtocolTest02(void)
696 {
697  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", true);
698  FAIL_IF_NULL(data);
699  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
700  FAIL_IF(data->negated == 0);
701  DetectAppLayerProtocolFree(NULL, data);
702  PASS;
703 }
704 
705 static int DetectAppLayerProtocolTest03(void)
706 {
707  Signature *s = NULL;
708  DetectAppLayerProtocolData *data = NULL;
711  de_ctx->flags |= DE_QUIET;
712 
713  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
714  "(app-layer-protocol:http; sid:1;)");
715  FAIL_IF_NULL(s);
716 
718 
721 
723  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
724  FAIL_IF(data->negated);
726  PASS;
727 }
728 
729 static int DetectAppLayerProtocolTest04(void)
730 {
731  Signature *s = NULL;
732  DetectAppLayerProtocolData *data = NULL;
735  de_ctx->flags |= DE_QUIET;
736 
737  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
738  "(app-layer-protocol:!http; sid:1;)");
739  FAIL_IF_NULL(s);
742 
745 
747  FAIL_IF_NULL(data);
748  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
749  FAIL_IF(data->negated == 0);
750 
752  PASS;
753 }
754 
755 static int DetectAppLayerProtocolTest05(void)
756 {
757  Signature *s = NULL;
758  DetectAppLayerProtocolData *data = NULL;
761  de_ctx->flags |= DE_QUIET;
762 
763  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
764  "(app-layer-protocol:!http; app-layer-protocol:!smtp; sid:1;)");
765  FAIL_IF_NULL(s);
768 
771 
773  FAIL_IF_NULL(data);
774  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
775  FAIL_IF(data->negated == 0);
776 
778  FAIL_IF_NULL(data);
779  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_SMTP));
780  FAIL_IF(data->negated == 0);
781 
783  PASS;
784 }
785 
786 static int DetectAppLayerProtocolTest06(void)
787 {
788  Signature *s = NULL;
791  de_ctx->flags |= DE_QUIET;
792 
793  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
794  "(app-layer-protocol:smtp; sid:1;)");
795  FAIL_IF_NOT_NULL(s);
797  PASS;
798 }
799 
800 static int DetectAppLayerProtocolTest07(void)
801 {
802  Signature *s = NULL;
805  de_ctx->flags |= DE_QUIET;
806 
807  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
808  "(app-layer-protocol:!smtp; sid:1;)");
809  FAIL_IF_NOT_NULL(s);
811  PASS;
812 }
813 
814 static int DetectAppLayerProtocolTest08(void)
815 {
816  Signature *s = NULL;
819  de_ctx->flags |= DE_QUIET;
820 
821  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
822  "(app-layer-protocol:!smtp; app-layer-protocol:http; sid:1;)");
823  FAIL_IF_NOT_NULL(s);
825  PASS;
826 }
827 
828 static int DetectAppLayerProtocolTest09(void)
829 {
830  Signature *s = NULL;
833  de_ctx->flags |= DE_QUIET;
834 
835  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
836  "(app-layer-protocol:http; app-layer-protocol:!smtp; sid:1;)");
837  FAIL_IF_NOT_NULL(s);
839  PASS;
840 }
841 
842 static int DetectAppLayerProtocolTest10(void)
843 {
844  Signature *s = NULL;
847  de_ctx->flags |= DE_QUIET;
848 
849  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
850  "(app-layer-protocol:smtp; app-layer-protocol:!http; sid:1;)");
851  FAIL_IF_NOT_NULL(s);
853  PASS;
854 }
855 
856 static int DetectAppLayerProtocolTest11(void)
857 {
858  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", false);
859  FAIL_IF_NULL(data);
860  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_FAILED));
861  FAIL_IF(data->negated != 0);
862  DetectAppLayerProtocolFree(NULL, data);
863  PASS;
864 }
865 
866 static int DetectAppLayerProtocolTest12(void)
867 {
868  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", true);
869  FAIL_IF_NULL(data);
870  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_FAILED));
871  FAIL_IF(data->negated == 0);
872  DetectAppLayerProtocolFree(NULL, data);
873  PASS;
874 }
875 
876 static int DetectAppLayerProtocolTest13(void)
877 {
878  Signature *s = NULL;
879  DetectAppLayerProtocolData *data = NULL;
882  de_ctx->flags |= DE_QUIET;
883 
884  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
885  "(app-layer-protocol:failed; sid:1;)");
886  FAIL_IF_NULL(s);
887 
889 
892 
894  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_FAILED));
895  FAIL_IF(data->negated);
897  PASS;
898 }
899 
900 static int DetectAppLayerProtocolTest14(void)
901 {
902  DetectAppLayerProtocolData *data = NULL;
905  de_ctx->flags |= DE_QUIET;
906 
907  Signature *s1 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
908  "(app-layer-protocol:http; flowbits:set,blah; sid:1;)");
909  FAIL_IF_NULL(s1);
914  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
915  FAIL_IF(data->negated);
916 
917  Signature *s2 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
918  "(app-layer-protocol:http; flow:to_client; sid:2;)");
919  FAIL_IF_NULL(s2);
924  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
925  FAIL_IF(data->negated);
926 
927  /* flow:established and other options not supported for PD-only */
928  Signature *s3 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
929  "(app-layer-protocol:http; flow:to_client,established; sid:3;)");
930  FAIL_IF_NULL(s3);
935  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
936  FAIL_IF(data->negated);
937 
941  FAIL_IF(s3->type == SIG_TYPE_PDONLY); // failure now
942 
944  PASS;
945 }
946 
947 static int DetectAppLayerProtocolTest15(void)
948 {
949  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http,final", false);
950  FAIL_IF_NULL(data);
951  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
952  FAIL_IF(data->negated != 0);
954  FAIL_IF(data->is_list);
955  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
956  DetectAppLayerProtocolFree(NULL, data);
957  PASS;
958 }
959 
960 /** \test Multi-value without mode qualifier. */
961 static int DetectAppLayerProtocolTest16(void)
962 {
963  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls|http", false);
964  FAIL_IF_NULL(data);
965  FAIL_IF_NOT(data->is_list);
966  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_TLS));
967  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
968  FAIL_IF(data->mode != DETECT_ALPROTO_DIRECTION); /* default */
969  FAIL_IF(data->negated != 0);
970  DetectAppLayerProtocolFree(NULL, data);
971  PASS;
972 }
973 
974 /** \test Multi-value with mode qualifier. */
975 static int DetectAppLayerProtocolTest17(void)
976 {
977  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls|http,either", false);
978  FAIL_IF_NULL(data);
979  FAIL_IF_NOT(data->is_list);
980  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_TLS));
981  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
983  DetectAppLayerProtocolFree(NULL, data);
984  PASS;
985 }
986 
987 /** \test A bare mode name with no protocol is treated as a protocol lookup (fails). */
988 static int DetectAppLayerProtocolTest18(void)
989 {
990  /* "final" alone is treated as a protocol name (which won't resolve). */
991  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("final", false);
992  FAIL_IF_NOT_NULL(data);
993  PASS;
994 }
995 
996 /** \test Multi-value list with an explicit 'direction' mode qualifier. */
997 static int DetectAppLayerProtocolTest19(void)
998 {
999  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls|http,direction", false);
1000  FAIL_IF_NULL(data);
1001  FAIL_IF_NOT(data->is_list);
1002  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_TLS));
1003  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
1005  DetectAppLayerProtocolFree(NULL, data);
1006  PASS;
1007 }
1008 
1009 /** \test Empty value list rejected. */
1010 static int DetectAppLayerProtocolTest20(void)
1011 {
1012  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("", false);
1013  FAIL_IF_NOT_NULL(data);
1014  PASS;
1015 }
1016 
1017 /** \test Negation of 'unknown' rejected. */
1018 static int DetectAppLayerProtocolTest21(void)
1019 {
1020  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("unknown", true);
1021  FAIL_IF_NOT_NULL(data);
1022  PASS;
1023 }
1024 
1025 /** \test Oversized argument length rejected. */
1026 static int DetectAppLayerProtocolTest22(void)
1027 {
1028  /* Build a string >1024 characters. */
1029  char big[1030];
1030  memset(big, 'a', sizeof(big) - 1);
1031  big[sizeof(big) - 1] = '\0';
1032  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse(big, false);
1033  FAIL_IF_NOT_NULL(data);
1034  PASS;
1035 }
1036 
1037 /** \test Empty token in pipe-separated list rejected. */
1038 static int DetectAppLayerProtocolTest23(void)
1039 {
1040  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls||http", false);
1041  FAIL_IF_NOT_NULL(data);
1042  PASS;
1043 }
1044 
1045 /** \test Negated multi-value parses correctly (!tls|http). */
1046 static int DetectAppLayerProtocolTest24(void)
1047 {
1048  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls|http", true);
1049  FAIL_IF_NULL(data);
1050  FAIL_IF(data->negated != 1);
1051  FAIL_IF_NOT(data->is_list);
1052  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_TLS));
1053  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_HTTP));
1054  DetectAppLayerProtocolFree(NULL, data);
1055  PASS;
1056 }
1057 
1058 /** \test Unknown protocol name in list rejected. */
1059 static int DetectAppLayerProtocolTest25(void)
1060 {
1061  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls|bogus_proto_xyz", false);
1062  FAIL_IF_NOT_NULL(data);
1063  PASS;
1064 }
1065 
1066 /** \test Negated single-value against unclassified flow returns 0. */
1067 static int DetectAppLayerProtocolTest26(void)
1068 {
1071  de_ctx->flags |= DE_QUIET;
1072 
1073  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1074  "(app-layer-protocol:!tls; sid:1;)");
1075  FAIL_IF_NULL(s);
1076 
1077  /* Check data BEFORE SigGroupBuild (init_data is freed by build). */
1079  FAIL_IF_NULL(sm);
1081  FAIL_IF_NULL(data);
1082  FAIL_IF(data->negated != 1);
1083  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_TLS));
1084 
1087  PASS;
1088 }
1089 
1090 /** \test Multi-value rule is NOT prefiltered. */
1091 static int DetectAppLayerProtocolTest27(void)
1092 {
1095  de_ctx->flags |= DE_QUIET;
1096 
1097  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1098  "(app-layer-protocol:tls|dns; sid:1;)");
1099  FAIL_IF_NULL(s);
1100 
1101  /* Verify the parsed data is list-valued BEFORE SigGroupBuild. */
1103  FAIL_IF_NULL(sm);
1105  FAIL_IF_NULL(data);
1106  FAIL_IF_NOT(data->is_list);
1107 
1108  /* A single-valued packet-detect-only rule is prefilter-eligible; the
1109  * multi-value guard must exclude this one. init_data is read by the
1110  * predicate, so check before SigGroupBuild frees it. */
1111  s->type = SIG_TYPE_PDONLY;
1112  FAIL_IF(PrefilterAppProtoIsPrefilterable(s));
1113 
1115  PASS;
1116 }
1117 
1118 /** \test Multi-value rule combined with buffer-keyword that pre-binds s->alproto is rejected. */
1119 static int DetectAppLayerProtocolTest28(void)
1120 {
1123  de_ctx->flags |= DE_QUIET;
1124 
1125  /* tls.sni binds s->alproto = TLS, so app-layer-protocol:tls|dns is rejected. */
1127  "alert tcp any any -> any any "
1128  "(tls.sni; content:\"example.com\"; app-layer-protocol:tls|dns; sid:1;)");
1129  FAIL_IF_NOT_NULL(s);
1130 
1132  PASS;
1133 }
1134 
1135 /** \test Default matching keeps AppProtoEquals equivalences (dns covers doh2). */
1136 static int DetectAppLayerProtocolTest29(void)
1137 {
1138  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("dns", false);
1139  FAIL_IF_NULL(data);
1140  FAIL_IF(data->exact);
1141  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_DNS));
1142  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_DOH2));
1143  DetectAppLayerProtocolFree(NULL, data);
1144  PASS;
1145 }
1146 
1147 /** \test The exact option drops equivalences (dns no longer covers doh2). */
1148 static int DetectAppLayerProtocolTest30(void)
1149 {
1150  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("dns,exact", false);
1151  FAIL_IF_NULL(data);
1152  FAIL_IF_NOT(data->exact);
1153  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_DNS));
1154  FAIL_IF(AlprotoBitmaskTest(data->alprotos, ALPROTO_DOH2));
1155  DetectAppLayerProtocolFree(NULL, data);
1156  PASS;
1157 }
1158 
1159 /** \test 'http' with 'exact' is rejected (can never match a real flow). */
1160 static int DetectAppLayerProtocolTest31(void)
1161 {
1162  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http,exact", false);
1163  FAIL_IF_NOT_NULL(data);
1164  PASS;
1165 }
1166 
1167 /** \test exact combines with a direction mode, order-independent. */
1168 static int DetectAppLayerProtocolTest32(void)
1169 {
1170  DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("tls|dns,either,exact", false);
1171  FAIL_IF_NULL(data);
1172  FAIL_IF_NOT(data->exact);
1173  FAIL_IF_NOT(data->is_list);
1175  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_TLS));
1176  FAIL_IF_NOT(AlprotoBitmaskTest(data->alprotos, ALPROTO_DNS));
1177  FAIL_IF(AlprotoBitmaskTest(data->alprotos, ALPROTO_DOH2));
1178  DetectAppLayerProtocolFree(NULL, data);
1179  PASS;
1180 }
1181 
1182 /** \test Single-value rule IS prefilter-eligible (mirror of Test27). */
1183 static int DetectAppLayerProtocolTest33(void)
1184 {
1187  de_ctx->flags |= DE_QUIET;
1188 
1189  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1190  "(app-layer-protocol:tls; sid:1;)");
1191  FAIL_IF_NULL(s);
1192 
1194  FAIL_IF_NULL(sm);
1196  FAIL_IF_NULL(data);
1197  FAIL_IF(data->is_list);
1198 
1199  /* A single-valued packet-detect-only rule is prefilter-eligible. init_data
1200  * is read by the predicate, so check before SigGroupBuild frees it. */
1201  s->type = SIG_TYPE_PDONLY;
1202  FAIL_IF_NOT(PrefilterAppProtoIsPrefilterable(s));
1203 
1205  PASS;
1206 }
1207 
1208 static void DetectAppLayerProtocolRegisterTests(void)
1209 {
1210  UtRegisterTest("DetectAppLayerProtocolTest01", DetectAppLayerProtocolTest01);
1211  UtRegisterTest("DetectAppLayerProtocolTest02", DetectAppLayerProtocolTest02);
1212  UtRegisterTest("DetectAppLayerProtocolTest03", DetectAppLayerProtocolTest03);
1213  UtRegisterTest("DetectAppLayerProtocolTest04", DetectAppLayerProtocolTest04);
1214  UtRegisterTest("DetectAppLayerProtocolTest05", DetectAppLayerProtocolTest05);
1215  UtRegisterTest("DetectAppLayerProtocolTest06", DetectAppLayerProtocolTest06);
1216  UtRegisterTest("DetectAppLayerProtocolTest07", DetectAppLayerProtocolTest07);
1217  UtRegisterTest("DetectAppLayerProtocolTest08", DetectAppLayerProtocolTest08);
1218  UtRegisterTest("DetectAppLayerProtocolTest09", DetectAppLayerProtocolTest09);
1219  UtRegisterTest("DetectAppLayerProtocolTest10", DetectAppLayerProtocolTest10);
1220  UtRegisterTest("DetectAppLayerProtocolTest11", DetectAppLayerProtocolTest11);
1221  UtRegisterTest("DetectAppLayerProtocolTest12", DetectAppLayerProtocolTest12);
1222  UtRegisterTest("DetectAppLayerProtocolTest13", DetectAppLayerProtocolTest13);
1223  UtRegisterTest("DetectAppLayerProtocolTest14", DetectAppLayerProtocolTest14);
1224  UtRegisterTest("DetectAppLayerProtocolTest15", DetectAppLayerProtocolTest15);
1225  UtRegisterTest("DetectAppLayerProtocolTest16", DetectAppLayerProtocolTest16);
1226  UtRegisterTest("DetectAppLayerProtocolTest17", DetectAppLayerProtocolTest17);
1227  UtRegisterTest("DetectAppLayerProtocolTest18", DetectAppLayerProtocolTest18);
1228  UtRegisterTest("DetectAppLayerProtocolTest19", DetectAppLayerProtocolTest19);
1229  UtRegisterTest("DetectAppLayerProtocolTest20", DetectAppLayerProtocolTest20);
1230  UtRegisterTest("DetectAppLayerProtocolTest21", DetectAppLayerProtocolTest21);
1231  UtRegisterTest("DetectAppLayerProtocolTest22", DetectAppLayerProtocolTest22);
1232  UtRegisterTest("DetectAppLayerProtocolTest23", DetectAppLayerProtocolTest23);
1233  UtRegisterTest("DetectAppLayerProtocolTest24", DetectAppLayerProtocolTest24);
1234  UtRegisterTest("DetectAppLayerProtocolTest25", DetectAppLayerProtocolTest25);
1235  UtRegisterTest("DetectAppLayerProtocolTest26", DetectAppLayerProtocolTest26);
1236  UtRegisterTest("DetectAppLayerProtocolTest27", DetectAppLayerProtocolTest27);
1237  UtRegisterTest("DetectAppLayerProtocolTest28", DetectAppLayerProtocolTest28);
1238  UtRegisterTest("DetectAppLayerProtocolTest29", DetectAppLayerProtocolTest29);
1239  UtRegisterTest("DetectAppLayerProtocolTest30", DetectAppLayerProtocolTest30);
1240  UtRegisterTest("DetectAppLayerProtocolTest31", DetectAppLayerProtocolTest31);
1241  UtRegisterTest("DetectAppLayerProtocolTest32", DetectAppLayerProtocolTest32);
1242  UtRegisterTest("DetectAppLayerProtocolTest33", DetectAppLayerProtocolTest33);
1243 }
1244 #endif /* UNITTESTS */
SigTableElmt_::url
const char * url
Definition: detect.h:1521
detect-engine.h
detect-app-layer-protocol.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:656
SigTableElmt_::desc
const char * desc
Definition: detect.h:1520
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1505
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:47
DetectAppLayerProtocolData_::mode
uint8_t mode
Definition: detect-app-layer-protocol.h:50
SigTableElmt_::name
const char * name
Definition: detect.h:1518
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1693
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
AppLayerGetProtoByName
AppProto AppLayerGetProtoByName(const char *alproto_name)
Given a protocol string, returns the corresponding internal protocol id.
Definition: app-layer.c:1007
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1509
ALPROTO_TLS
@ ALPROTO_TLS
Definition: app-layer-protos.h:39
PcapPacketCntGet
uint64_t PcapPacketCntGet(const Packet *p)
Definition: decode.c:1180
Signature_::alproto
AppProto alproto
Definition: detect.h:687
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectAppLayerProtocolData_
Per-rule keyword data for app-layer-protocol:.
Definition: detect-app-layer-protocol.h:45
name
const char * name
Definition: detect-engine-proto.c:48
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
Packet_::flags
uint32_t flags
Definition: decode.h:562
DetectAppLayerProtocolData_::alprotos
uint8_t * alprotos
Definition: detect-app-layer-protocol.h:51
SIGMATCH_QUOTES_OPTIONAL
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect-engine-register.h:316
Flow_
Flow data structure.
Definition: flow.h:354
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1408
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:41
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:981
Flow_::alproto_orig
AppProto alproto_orig
Definition: flow.h:456
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2872
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:24
DetectAppLayerProtocolModeName
const char * DetectAppLayerProtocolModeName(uint8_t mode)
Map a DETECT_ALPROTO_* mode value to its textual qualifier.
Definition: detect-app-layer-protocol.c:196
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:231
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
m
SCMutex m
Definition: flow-hash.h:6
p
Packet * p
Definition: fuzz_iprep.c:21
DetectAppLayerProtocolData_::exact
bool exact
Definition: detect-app-layer-protocol.h:48
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3802
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:547
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1500
PrefilterPacketHeaderValue::u16
uint16_t u16[8]
Definition: detect-engine-prefilter-common.h:25
detect-engine-prefilter.h
DETECT_ALPROTO_TOCLIENT
@ DETECT_ALPROTO_TOCLIENT
Definition: detect-app-layer-protocol.c:47
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
PKT_PROTO_DETECT_TS_DONE
#define PKT_PROTO_DETECT_TS_DONE
Definition: decode.h:1344
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:248
DetectAppLayerProtocolGetValues
uint16_t DetectAppLayerProtocolGetValues(const DetectAppLayerProtocolData *data, AppProto *out, uint16_t max)
Fill out[] with the keyword's set protocol values.
Definition: detect-app-layer-protocol.c:217
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1503
DETECT_APP_LAYER_PROTOCOL
@ DETECT_APP_LAYER_PROTOCOL
Definition: detect-engine-register.h:35
app-layer-detect-proto.h
MAX_ALPROTO_NAME
#define MAX_ALPROTO_NAME
Definition: detect-app-layer-protocol.c:173
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:35
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:30
DetectEngineThreadCtx_
Definition: detect.h:1300
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
SIG_MASK_REQUIRE_FLOW
#define SIG_MASK_REQUIRE_FLOW
Definition: detect.h:312
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:387
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:360
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:117
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:359
DETECT_ALPROTO_FINAL
@ DETECT_ALPROTO_FINAL
Definition: detect-app-layer-protocol.c:44
SCReturn
#define SCReturn
Definition: util-debug.h:286
DETECT_ALPROTO_EITHER
@ DETECT_ALPROTO_EITHER
Definition: detect-app-layer-protocol.c:45
Signature_::flags
uint32_t flags
Definition: detect.h:683
Packet_
Definition: decode.h:516
detect-engine-build.h
DETECT_ALPROTO_DIRECTION
@ DETECT_ALPROTO_DIRECTION
Definition: detect-app-layer-protocol.c:43
ALPROTO_DOH2
@ ALPROTO_DOH2
Definition: app-layer-protos.h:66
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:761
PrefilterSetupPacketHeader
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, SignatureMask mask, void(*Set)(PrefilterPacketHeaderValue *v, void *), bool(*Compare)(PrefilterPacketHeaderValue v, void *), void(*Match)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx))
Definition: detect-engine-prefilter-common.c:470
DetectAppLayerProtocolData_::alproto
AppProto alproto
Definition: detect-app-layer-protocol.h:46
SignatureInitData_::negated
bool negated
Definition: detect.h:604
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1480
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2295
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:351
Packet_::flow
struct Flow_ * flow
Definition: decode.h:564
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:357
PKT_PROTO_DETECT_TC_DONE
#define PKT_PROTO_DETECT_TC_DONE
Definition: decode.h:1345
AppLayerProtoDetectSupportedAppProtocols
void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos)
Definition: app-layer-detect-proto.c:2141
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alproto_ts
AppProto alproto_ts
Definition: flow.h:451
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1502
detect-parse.h
Signature_
Signature container.
Definition: detect.h:682
SigMatch_
a single match condition for a signature
Definition: detect.h:356
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:77
DETECT_ALPROTO_ORIG
@ DETECT_ALPROTO_ORIG
Definition: detect-app-layer-protocol.c:48
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:33
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2833
DETECT_ALPROTO_TOSERVER
@ DETECT_ALPROTO_TOSERVER
Definition: detect-app-layer-protocol.c:46
DetectAppLayerProtocolRegister
void DetectAppLayerProtocolRegister(void)
Definition: detect-app-layer-protocol.c:663
DetectAppLayerProtocolData_::negated
bool negated
Definition: detect-app-layer-protocol.h:47
SIGMATCH_SUPPORT_FIREWALL
#define SIGMATCH_SUPPORT_FIREWALL
Definition: detect-engine-register.h:334
PrefilterPacketHeaderValue
Definition: detect-engine-prefilter-common.h:23
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:983
detect-engine-prefilter-common.h
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:452
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
DetectAppLayerProtocolData_::is_list
bool is_list
Definition: detect-app-layer-protocol.h:49
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
Signature_::type
enum SignatureType type
Definition: detect.h:685
SIGMATCH_HANDLE_NEGATION
#define SIGMATCH_HANDLE_NEGATION
Definition: detect-engine-register.h:324
SIG_TYPE_PDONLY
@ SIG_TYPE_PDONLY
Definition: detect.h:70
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1507
app-layer.h