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