suricata
detect-engine-siggroup.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Signature grouping part of the detection engine.
24  */
25 
26 #include "suricata-common.h"
27 #include "decode.h"
28 
29 #include "flow-var.h"
30 
31 #include "app-layer-protos.h"
32 
33 #include "detect.h"
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-engine-build.h"
37 #include "detect-engine-address.h"
38 #include "detect-engine-mpm.h"
39 #include "detect-engine-siggroup.h"
41 
42 #include "detect-content.h"
43 #include "detect-uricontent.h"
44 #include "detect-tcp-flags.h"
45 
46 #include "util-hash.h"
47 #include "util-hashlist.h"
48 
49 #include "util-error.h"
50 #include "util-debug.h"
51 #include "util-validate.h"
52 #include "util-cidr.h"
53 #include "util-unittest-helper.h"
54 #include "util-memcmp.h"
55 
56 /* prototypes */
58 
60 {
61  if (sghid->match_array != NULL) {
62  SCFree(sghid->match_array);
63  sghid->match_array = NULL;
64  }
65  if (sghid->sig_array != NULL) {
66  SCFreeAligned(sghid->sig_array);
67  sghid->sig_array = NULL;
68  }
69  if (sghid->app_mpms != NULL) {
70  SCFree(sghid->app_mpms);
71  }
72  if (sghid->pkt_mpms != NULL) {
73  SCFree(sghid->pkt_mpms);
74  }
75  if (sghid->frame_mpms != NULL) {
76  SCFree(sghid->frame_mpms);
77  }
78 
84 
85  SCFree(sghid);
86 }
87 
88 static SigGroupHeadInitData *SigGroupHeadInitDataAlloc(uint32_t size)
89 {
91  if (unlikely(sghid == NULL))
92  return NULL;
93 
94  /* initialize the signature bitarray */
95  size = sghid->sig_size = size + 16 - (size % 16);
96  void *ptr = SCMallocAligned(sghid->sig_size, 16);
97  if (ptr == NULL)
98  goto error;
99  memset(ptr, 0, size);
100  sghid->sig_array = ptr;
101 
102  return sghid;
103 error:
105  return NULL;
106 }
107 
109 {
110  void *ptmp;
111  //printf("de_ctx->sgh_array_cnt %u, de_ctx->sgh_array_size %u, de_ctx->sgh_array %p\n", de_ctx->sgh_array_cnt, de_ctx->sgh_array_size, de_ctx->sgh_array);
114  } else {
115  int increase = 16;
116  ptmp = SCRealloc(de_ctx->sgh_array,
117  sizeof(SigGroupHead *) * (increase + de_ctx->sgh_array_size));
118  if (ptmp == NULL) {
120  de_ctx->sgh_array = NULL;
121  return;
122  }
123  de_ctx->sgh_array = ptmp;
124 
125  de_ctx->sgh_array_size += increase;
127  }
129 }
130 
131 /**
132  * \brief Alloc a SigGroupHead and its signature bit_array.
133  *
134  * \param size Size of the sig_array that has to be created for this
135  * SigGroupHead.
136  *
137  * \retval sgh Pointer to the newly init SigGroupHead on success; or NULL in
138  * case of error.
139  */
140 static SigGroupHead *SigGroupHeadAlloc(const DetectEngineCtx *de_ctx, uint32_t size)
141 {
142  SigGroupHead *sgh = SCCalloc(1, sizeof(SigGroupHead));
143  if (unlikely(sgh == NULL))
144  return NULL;
145 
146  sgh->init = SigGroupHeadInitDataAlloc(size);
147  if (sgh->init == NULL)
148  goto error;
149 
150  return sgh;
151 
152 error:
153  SigGroupHeadFree(de_ctx, sgh);
154  return NULL;
155 }
156 
157 /**
158  * \brief Free a SigGroupHead and its members.
159  *
160  * \param sgh Pointer to the SigGroupHead that has to be freed.
161  */
163 {
164  if (sgh == NULL)
165  return;
166 
167  SCLogDebug("sgh %p", sgh);
168 
169  if (sgh->init != NULL) {
171  sgh->init = NULL;
172  }
173 
175  SCFree(sgh);
176 }
177 
178 /**
179  * \brief The hash function to be the used by the hash table -
180  * DetectEngineCtx->sgh_hash_table.
181  *
182  * \param ht Pointer to the hash table.
183  * \param data Pointer to the SigGroupHead.
184  * \param datalen Not used in our case.
185  *
186  * \retval hash The generated hash value.
187  */
188 static uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen)
189 {
190  SigGroupHead *sgh = (SigGroupHead *)data;
191  uint32_t hash = 0;
192  uint32_t b = 0;
193 
194  SCLogDebug("hashing sgh %p", sgh);
195 
196  for (b = 0; b < sgh->init->sig_size; b++)
197  hash += sgh->init->sig_array[b];
198 
199  hash %= ht->array_size;
200  SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->init->sig_size);
201  return hash;
202 }
203 
204 /**
205  * \brief The Compare function to be used by the SigGroupHead hash table -
206  * DetectEngineCtx->sgh_hash_table.
207  *
208  * \param data1 Pointer to the first SigGroupHead.
209  * \param len1 Not used.
210  * \param data2 Pointer to the second SigGroupHead.
211  * \param len2 Not used.
212  *
213  * \retval 1 If the 2 SigGroupHeads sent as args match.
214  * \retval 0 If the 2 SigGroupHeads sent as args do not match.
215  */
216 static char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2,
217  uint16_t len2)
218 {
219  SigGroupHead *sgh1 = (SigGroupHead *)data1;
220  SigGroupHead *sgh2 = (SigGroupHead *)data2;
221 
222  if (data1 == NULL || data2 == NULL)
223  return 0;
224 
225  if (sgh1->init->sig_size != sgh2->init->sig_size)
226  return 0;
227 
228  if (SCMemcmp(sgh1->init->sig_array, sgh2->init->sig_array, sgh1->init->sig_size) != 0)
229  return 0;
230 
231  return 1;
232 }
233 
234 /**
235  * \brief Initializes the hash table in the detection engine context to hold the
236  * SigGroupHeads.
237  *
238  * \param de_ctx Pointer to the detection engine context.
239  *
240  * \retval 0 On success.
241  * \retval -1 On failure.
242  */
244 {
245  de_ctx->sgh_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc,
246  SigGroupHeadCompareFunc, NULL);
247  if (de_ctx->sgh_hash_table == NULL)
248  goto error;
249 
250  return 0;
251 
252 error:
253  return -1;
254 }
255 
256 /**
257  * \brief Adds a SigGroupHead to the detection engine context SigGroupHead
258  * hash table.
259  *
260  * \param de_ctx Pointer to the detection engine context.
261  * \param sgh Pointer to the SigGroupHead.
262  *
263  * \retval ret 0 on Successfully adding the SigGroupHead; -1 on failure.
264  */
266 {
267  int ret = HashListTableAdd(de_ctx->sgh_hash_table, (void *)sgh, 0);
268 
269  return ret;
270 }
271 
272 /**
273  * \brief Used to lookup a SigGroupHead hash from the detection engine context
274  * SigGroupHead hash table.
275  *
276  * \param de_ctx Pointer to the detection engine context.
277  * \param sgh Pointer to the SigGroupHead.
278  *
279  * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
280  * found in the hash table; NULL on failure.
281  */
283 {
284  SCEnter();
285 
287  (void *)sgh, 0);
288 
289  SCReturnPtr(rsgh, "SigGroupHead");
290 }
291 
292 /**
293  * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
294  * SigGroupHeadHashInit() function.
295  *
296  * \param de_ctx Pointer to the detection engine context.
297  */
299 {
300  if (de_ctx->sgh_hash_table == NULL)
301  return;
302 
304  de_ctx->sgh_hash_table = NULL;
305 }
306 
307 /**
308  * \brief Add a Signature to a SigGroupHead.
309  *
310  * \param de_ctx Pointer to the detection engine context.
311  * \param sgh Pointer to a SigGroupHead. Can be NULL also.
312  * \param s Pointer to the Signature that has to be added to the
313  * SigGroupHead.
314  *
315  * \retval 0 On success.
316  * \retval -1 On failure.
317  */
319  const Signature *s)
320 {
321  if (de_ctx == NULL)
322  return 0;
323 
324  /* see if we have a head already */
325  if (*sgh == NULL) {
326  *sgh = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
327  if (*sgh == NULL)
328  goto error;
329  }
330 
331  /* enable the sig in the bitarray */
332  (*sgh)->init->sig_array[s->iid / 8] |= 1 << (s->iid % 8);
333  (*sgh)->init->max_sig_id = MAX(s->iid, (*sgh)->init->max_sig_id);
334  return 0;
335 
336 error:
337  return -1;
338 }
339 
340 /**
341  * \brief Clears the bitarray holding the sids for this SigGroupHead.
342  *
343  * \param sgh Pointer to the SigGroupHead.
344  *
345  * \retval 0 Always.
346  */
348 {
349  if (sgh == NULL)
350  return 0;
351 
352  if (sgh->init->sig_array != NULL)
353  memset(sgh->init->sig_array, 0, sgh->init->sig_size);
354 
355  sgh->init->sig_cnt = 0;
356 
357  return 0;
358 }
359 
360 #ifdef __SSE2__
361 #include <emmintrin.h>
362 static void MergeBitarrays(const uint8_t *src, uint8_t *dst, const uint32_t size)
363 {
364 #define BYTES 16
365  const uint8_t *srcptr = src;
366  uint8_t *dstptr = dst;
367  for (uint32_t i = 0; i < size; i += 16) {
368  __m128i s = _mm_load_si128((const __m128i *)srcptr);
369  __m128i d = _mm_load_si128((const __m128i *)dstptr);
370  d = _mm_or_si128(s, d);
371  _mm_store_si128((__m128i *)dstptr, d);
372  srcptr += BYTES;
373  dstptr += BYTES;
374  }
375 }
376 #endif
377 
378 /**
379  * \brief Copies the bitarray holding the sids from the source SigGroupHead to
380  * the destination SigGroupHead.
381  *
382  * \param de_ctx Pointer to the detection engine context.
383  * \param src Pointer to the source SigGroupHead.
384  * \param dst Pointer to the destination SigGroupHead.
385  *
386  * \retval 0 On success.
387  * \retval -1 On failure.
388  */
390 {
391  if (src == NULL || de_ctx == NULL)
392  return 0;
393 
394  if (*dst == NULL) {
395  *dst = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
396  if (*dst == NULL)
397  goto error;
398  }
399  DEBUG_VALIDATE_BUG_ON(src->init->sig_size != (*dst)->init->sig_size);
400 
401 #ifdef __SSE2__
402  MergeBitarrays(src->init->sig_array, (*dst)->init->sig_array, src->init->sig_size);
403 #else
404  /* do the copy */
405  for (uint32_t idx = 0; idx < src->init->sig_size; idx++)
406  (*dst)->init->sig_array[idx] = (*dst)->init->sig_array[idx] | src->init->sig_array[idx];
407 #endif
408  if (src->init->score)
409  (*dst)->init->score = MAX((*dst)->init->score, src->init->score);
410 
411  if (src->init->max_sig_id)
412  (*dst)->init->max_sig_id = MAX((*dst)->init->max_sig_id, src->init->max_sig_id);
413  return 0;
414 
415 error:
416  return -1;
417 }
418 
419 #ifdef HAVE_POPCNT64
420 #include <x86intrin.h>
421 static uint32_t Popcnt(const uint8_t *array, const uint32_t size)
422 {
423  /* input needs to be a multiple of 8 for u64 casts to work */
424  DEBUG_VALIDATE_BUG_ON(size < 8);
425  DEBUG_VALIDATE_BUG_ON(size % 8);
426 
427  uint32_t cnt = 0;
428  uint64_t *ptr = (uint64_t *)array;
429  for (uint64_t idx = 0; idx < size; idx += 8) {
430  cnt += _popcnt64(*ptr);
431  ptr++;
432  }
433  return cnt;
434 }
435 #endif
436 
437 /**
438  * \brief Updates the SigGroupHead->sig_cnt with the total count of all the
439  * Signatures present in this SigGroupHead.
440  *
441  * \param sgh Pointer to the SigGroupHead.
442  * \param max_idx Maximum sid of the all the Signatures present in this
443  * SigGroupHead.
444  */
445 void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
446 {
447  sgh->init->max_sig_id = MAX(max_idx, sgh->init->max_sig_id);
448 #ifdef HAVE_POPCNT64
449  sgh->init->sig_cnt = Popcnt(sgh->init->sig_array, sgh->init->sig_size);
450 #else
451  uint32_t cnt = 0;
452  for (uint32_t sig = 0; sig < sgh->init->max_sig_id + 1; sig++) {
453  if (sgh->init->sig_array[sig / 8] & (1 << (sig % 8)))
454  cnt++;
455  }
456  sgh->init->sig_cnt = cnt;
457 #endif
458 }
459 
460 /**
461  * \brief Finds if two Signature Group Heads are the same.
462  *
463  * \param sgha First SGH to be compared
464  * \param sghb Secornd SGH to be compared
465  *
466  * \return true if they're a match, false otherwise
467  */
468 bool SigGroupHeadEqual(const SigGroupHead *sgha, const SigGroupHead *sghb)
469 {
470  if (sgha == NULL || sghb == NULL)
471  return false;
472 
473  if (sgha->init->sig_size != sghb->init->sig_size)
474  return false;
475 
476  if (sgha->init->max_sig_id != sghb->init->max_sig_id)
477  return false;
478 
479  return SCMemcmp(sgha->init->sig_array, sghb->init->sig_array, sgha->init->sig_size) == 0;
480 }
481 
483  uint8_t ipproto, int dir)
484 {
485  if (sgh && sgh->init) {
486  SCLogDebug("setting proto %u and dir %d on sgh %p", ipproto, dir, sgh);
487  sgh->init->protos[ipproto] = 1;
488  sgh->init->direction |= dir;
489  }
490 }
491 
492 /**
493  * \brief Helper function used to print the list of sids for the Signatures
494  * present in this SigGroupHead.
495  *
496  * \param de_ctx Pointer to the detection engine context.
497  * \param sgh Pointer to the SigGroupHead.
498  */
500 {
501  SCEnter();
502 
503  if (sgh == NULL) {
504  SCReturn;
505  }
506 
507  uint32_t u;
508 
509  SCLogDebug("The Signatures present in this SigGroupHead are: ");
510  for (u = 0; u < (sgh->init->sig_size * 8); u++) {
511  if (sgh->init->sig_array[u / 8] & (1 << (u % 8))) {
512  SCLogDebug("%" PRIu32, u);
513  printf("s->iid %" PRIu32 " ", u);
514  }
515  }
516 
517  SCReturn;
518 }
519 
520 /**
521  * \brief Create an array with all the internal ids of the sigs that this
522  * sig group head will check for.
523  *
524  * \param de_ctx Pointer to the detection engine context.
525  * \param sgh Pointer to the SigGroupHead.
526  * \param max_idx The maximum value of the sid in the SigGroupHead arg.
527  *
528  * \retval 0 success
529  * \retval -1 error
530  */
532  uint32_t max_idx)
533 {
534  Signature *s = NULL;
535  uint32_t idx = 0;
536  uint32_t sig = 0;
537 
538  if (sgh == NULL)
539  return 0;
540 
541  BUG_ON(sgh->init->match_array != NULL);
542  sgh->init->max_sig_id = MAX(sgh->init->max_sig_id, max_idx);
543 
544  sgh->init->match_array = SCCalloc(sgh->init->sig_cnt, sizeof(Signature *));
545  if (sgh->init->match_array == NULL)
546  return -1;
547 
548  for (sig = 0; sig < sgh->init->max_sig_id + 1; sig++) {
549  if (!(sgh->init->sig_array[(sig / 8)] & (1 << (sig % 8))) )
550  continue;
551 
552  s = de_ctx->sig_array[sig];
553  if (s == NULL)
554  continue;
555 
556  sgh->init->match_array[idx] = s;
557  idx++;
558  }
559 
560  return 0;
561 }
562 
563 /**
564  * \brief Set the need hash flag in the sgh.
565  *
566  * \param de_ctx detection engine ctx for the signatures
567  * \param sgh sig group head to update
568  */
570 {
571  if (sgh == NULL)
572  return;
573 
574  for (uint32_t sig = 0; sig < sgh->init->sig_cnt; sig++) {
575  const Signature *s = sgh->init->match_array[sig];
576  if (s == NULL)
577  continue;
578 
581  SCLogDebug("sgh %p has filemd5", sgh);
582  }
585  SCLogDebug("sgh %p has filesha1", sgh);
586  }
589  SCLogDebug("sgh %p has filesha256", sgh);
590  }
591 #ifdef HAVE_MAGIC
593  sgh->flags |= SIG_GROUP_HEAD_HAVEFILEMAGIC;
594  }
595 #endif
596  if (SignatureIsFilestoring(s)) {
597  // should be insured by caller that we do not overflow
598  DEBUG_VALIDATE_BUG_ON(sgh->filestore_cnt == UINT16_MAX);
599  sgh->filestore_cnt++;
600  }
601  }
602 }
603 
604 /**
605  * \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an
606  * argument.
607  *
608  * \param de_ctx Pointer to the detection engine context.
609  * \param sgh Pointer to the SigGroupHead that has to be checked for the
610  * presence of a Signature.
611  * \param sid The Signature id(sid) that has to be checked in the SigGroupHead.
612  *
613  * \retval 1 On successfully finding the sid in the SigGroupHead.
614  * \retval 0 If the sid is not found in the SigGroupHead
615  */
617  uint32_t sid)
618 {
619  SCEnter();
620 
621  uint32_t sig = 0;
622  Signature *s = NULL;
623  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx);
624 
625  if (sgh == NULL) {
626  SCReturnInt(0);
627  }
628 
629  for (sig = 0; sig < max_sid; sig++) {
630  if (sgh->init->sig_array == NULL) {
631  SCReturnInt(0);
632  }
633 
634  /* Check if the SigGroupHead has an entry for the sid */
635  if ( !(sgh->init->sig_array[sig / 8] & (1 << (sig % 8))) )
636  continue;
637 
638  /* If we have reached here, we have an entry for sid in the SigGroupHead.
639  * Retrieve the Signature from the detection engine context */
640  s = de_ctx->sig_array[sig];
641  if (s == NULL)
642  continue;
643 
644  /* If the retrieved Signature matches the sid arg, we have a match */
645  if (s->id == sid) {
646  SCReturnInt(1);
647  }
648  }
649 
650  SCReturnInt(0);
651 }
652 
653 /*----------------------------------Unittests---------------------------------*/
654 
655 #ifdef UNITTESTS
656 
658 
659 /**
660  * \test Check if a SigGroupHead hash table is properly allocated and
661  * deallocated when calling SigGroupHeadHashInit() and
662  * SigGroupHeadHashFree() respectively.
663  */
664 static int SigGroupHeadTest01(void)
665 {
667 
670 
673 
674  PASS;
675 }
676 
677 /**
678  * \test Check if a SigGroupHeadAppendSig() correctly appends a sid to a
679  * SigGroupHead() and SigGroupHeadContainsSigId() correctly indicates
680  * the presence of a sid.
681  */
682 static int SigGroupHeadTest02(void)
683 {
684  SigGroupHead *sh = NULL;
685 
688 
689  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
690  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
691  "content:\"test2\"; content:\"test3\"; sid:1;)");
692  FAIL_IF_NULL(s);
693 
694  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
695  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
696  "content:\"test2\"; content:\"test3\"; sid:2;)");
697  FAIL_IF_NULL(s);
698 
699  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
700  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
701  "content:\"test2\"; content:\"test3\"; sid:3;)");
702  FAIL_IF_NULL(s);
703 
704  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
705  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
706  "content:\"test2\"; content:\"test3\"; sid:4;)");
707  FAIL_IF_NULL(s);
708 
709  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
710  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
711  "content:\"test2\"; content:\"test3\"; sid:5;)");
712  FAIL_IF_NULL(s);
713 
715 
719 
720  SigGroupHeadSetSigCnt(sh, 4);
721 
722  FAIL_IF_NOT(sh->init->sig_cnt == 3);
728 
730 
732 
733  PASS;
734 }
735 
736 /**
737  * \test Check if a SigGroupHeadAppendSig(), correctly appends a sid to a
738  * SigGroupHead() and SigGroupHeadContainsSigId(), correctly indicates
739  * the presence of a sid and SigGroupHeadClearSigs(), correctly clears
740  * the SigGroupHead->sig_array and SigGroupHead->sig_cnt.
741  */
742 static int SigGroupHeadTest03(void)
743 {
744  SigGroupHead *sh = NULL;
745 
748 
749  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
750  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
751  "content:\"test2\"; content:\"test3\"; sid:1;)");
752  FAIL_IF_NULL(s);
753 
754  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
755  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
756  "content:\"test2\"; content:\"test3\"; sid:2;)");
757  FAIL_IF_NULL(s);
758 
759  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
760  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
761  "content:\"test2\"; content:\"test3\"; sid:3;)");
762  FAIL_IF_NULL(s);
763 
764  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
765  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
766  "content:\"test2\"; content:\"test3\"; sid:4;)");
767  FAIL_IF_NULL(s);
768 
769  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
770  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
771  "content:\"test2\"; content:\"test3\"; sid:5;)");
772  FAIL_IF_NULL(s);
773 
775 
779 
780  SigGroupHeadSetSigCnt(sh, 4);
781 
782  FAIL_IF_NOT(sh->init->sig_cnt == 3);
788 
790 
791  FAIL_IF_NOT(sh->init->sig_cnt == 0);
797 
799 
801 
802  PASS;
803 }
804 
805 /**
806  * \test Check if SigGroupHeadCopySigs(), correctly copies the sig_array from
807  * the source to the destination SigGroupHead.
808  */
809 static int SigGroupHeadTest04(void)
810 {
811  SigGroupHead *src_sh = NULL;
812  SigGroupHead *dst_sh = NULL;
814 
816 
817  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
818  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
819  "content:\"test2\"; content:\"test3\"; sid:1;)");
820  FAIL_IF_NULL(s);
821 
822  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
823  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
824  "content:\"test2\"; content:\"test3\"; sid:2;)");
825  FAIL_IF_NULL(s);
826 
827  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
828  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
829  "content:\"test2\"; content:\"test3\"; sid:3;)");
830  FAIL_IF_NULL(s);
831 
832  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
833  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
834  "content:\"test2\"; content:\"test3\"; sid:4;)");
835  FAIL_IF_NULL(s);
836 
837  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
838  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
839  "content:\"test2\"; content:\"test3\"; sid:5;)");
840  FAIL_IF_NULL(s);
841 
843 
847 
848  SigGroupHeadSetSigCnt(src_sh, 4);
849 
850  FAIL_IF_NOT(src_sh->init->sig_cnt == 3);
851  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 1) == 1);
852  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 2) == 0);
853  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 3) == 1);
854  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 4) == 0);
855  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 5) == 1);
856 
857  SigGroupHeadCopySigs(de_ctx, src_sh, &dst_sh);
858 
859  SigGroupHeadSetSigCnt(dst_sh, 4);
860 
861  FAIL_IF_NOT(dst_sh->init->sig_cnt == 3);
862  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 1) == 1);
863  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 2) == 0);
864  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 3) == 1);
865  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 4) == 0);
866  FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 5) == 1);
867 
868  SigGroupHeadFree(de_ctx, src_sh);
869  SigGroupHeadFree(de_ctx, dst_sh);
870 
872 
873  PASS;
874 }
875 
876 /**
877  * \test Check if SigGroupHeadBuildMatchArray(), correctly updates the
878  * match array with the sids.
879  */
880 static int SigGroupHeadTest05(void)
881 {
882  SigGroupHead *sh = NULL;
884 
886 
887  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
888  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
889  "content:\"test2\"; content:\"test3\"; sid:1;)");
890  FAIL_IF_NULL(s);
891 
892  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
893  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
894  "content:\"test2\"; content:\"test3\"; sid:2;)");
895  FAIL_IF_NULL(s);
896 
897  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
898  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
899  "content:\"test2\"; content:\"test3\"; sid:3;)");
900  FAIL_IF_NULL(s);
901 
902  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
903  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
904  "content:\"test2\"; content:\"test3\"; sid:4;)");
905  FAIL_IF_NULL(s);
906 
907  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
908  "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
909  "content:\"test2\"; content:\"test3\"; sid:5;)");
910  FAIL_IF_NULL(s);
911 
913 
917 
918  SigGroupHeadSetSigCnt(sh, 4);
920 
921  /* matching an array to a queue structure (sig_list) constructed by SigInit()
922 
923  FAIL_IF_NOT(sh->init->match_array[0] == de_ctx->sig_list);
924  FAIL_IF_NOT(sh->init->match_array[1] == de_ctx->sig_list->next->next);
925  FAIL_IF_NOT(sh->init->match_array[2] == de_ctx->sig_list->next->next->next->next);
926  */
927 
928  // matching an array to a stack structure (sig_list) constructed by DetectEngineAppendSig()
932 
934 
936 
937  PASS;
938 }
939 
940 /**
941  * \test ICMP(?) sig grouping bug.
942  */
943 static int SigGroupHeadTest06(void)
944 {
946  DetectEngineThreadCtx *det_ctx = NULL;
948 
949  memset(&th_v, 0, sizeof(ThreadVars));
951 
952  Packet *p = UTHBuildPacketSrcDst(NULL, 0, IPPROTO_ICMP, "192.168.1.1", "1.2.3.4");
953  FAIL_IF_NULL(p);
954  FAIL_IF_NOT(PacketIsICMPv4(p));
955 
956  p->l4.hdrs.icmpv4h->type = 5;
957  p->l4.hdrs.icmpv4h->code = 1;
958 
959  /* originally ip's were
960  p.src.addr_data32[0] = 0xe08102d3;
961  p.dst.addr_data32[0] = 0x3001a8c0;
962  */
963 
965 
966  Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp 192.168.0.0/16 any -> any any "
967  "(icode:>1; itype:11; sid:1; rev:1;)");
968  FAIL_IF_NULL(s);
969 
970  s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> 192.168.0.0/16 any "
971  "(icode:1; itype:5; sid:2; rev:1;)");
972  FAIL_IF_NULL(s);
973 
975  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
976 
978 
980  FAIL_IF_NULL(sgh);
981 
982  UTHFreePackets(&p, 1);
983 
984  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
987  PASS;
988 }
989 #endif
990 
992 {
993 #ifdef UNITTESTS
994  UtRegisterTest("SigGroupHeadTest01", SigGroupHeadTest01);
995  UtRegisterTest("SigGroupHeadTest02", SigGroupHeadTest02);
996  UtRegisterTest("SigGroupHeadTest03", SigGroupHeadTest03);
997  UtRegisterTest("SigGroupHeadTest04", SigGroupHeadTest04);
998  UtRegisterTest("SigGroupHeadTest05", SigGroupHeadTest05);
999  UtRegisterTest("SigGroupHeadTest06", SigGroupHeadTest06);
1000 #endif
1001 }
detect-tcp-flags.h
DetectEngineCtx_::sgh_hash_table
HashListTable * sgh_hash_table
Definition: detect.h:1029
SIG_GROUP_HEAD_HAVEFILEMD5
#define SIG_GROUP_HEAD_HAVEFILEMD5
Definition: detect.h:1578
detect-content.h
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
util-hashlist.h
detect-engine-siggroup.h
SigGroupHead_::flags
uint16_t flags
Definition: detect.h:1731
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1730
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SigGroupHeadEqual
bool SigGroupHeadEqual(const SigGroupHead *sgha, const SigGroupHead *sghb)
Finds if two Signature Group Heads are the same.
Definition: detect-engine-siggroup.c:468
SigGroupHeadInitData_::sig_array
uint8_t * sig_array
Definition: detect.h:1704
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
AddressDebugPrint
void AddressDebugPrint(Address *a)
Debug print function for printing addresses.
Definition: decode.c:826
UTHBuildPacketSrcDst
Packet * UTHBuildPacketSrcDst(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst)
UTHBuildPacketSrcDst is a wrapper that build packets specifying IPs and defaulting ports.
Definition: util-unittest-helper.c:403
util-hash.h
SIG_GROUP_HEAD_HAVEFILESHA1
#define SIG_GROUP_HEAD_HAVEFILESHA1
Definition: detect.h:1580
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
SigGroupHeadSetProtoAndDirection
void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh, uint8_t ipproto, int dir)
Definition: detect-engine-siggroup.c:482
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2912
SigPrepareStage1
int SigPrepareStage1(DetectEngineCtx *)
Preprocess signature, classify ip-only, etc, build sig array.
Definition: detect-engine-build.c:1785
SigGroupHeadPrintSigs
void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Helper function used to print the list of sids for the Signatures present in this SigGroupHead.
Definition: detect-engine-siggroup.c:499
p
Packet * p
Definition: fuzz_dataset.c:30
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:244
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3971
MAX
#define MAX(x, y)
Definition: suricata-common.h:417
SigGroupHeadSetupFiles
void SigGroupHeadSetupFiles(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Set the need hash flag in the sgh.
Definition: detect-engine-siggroup.c:569
detect-engine-prefilter.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
SigGroupHeadRegisterTests
void SigGroupHeadRegisterTests(void)
Definition: detect-engine-siggroup.c:991
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:113
SigGroupHeadHashInit
int SigGroupHeadHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table in the detection engine context to hold the SigGroupHeads.
Definition: detect-engine-siggroup.c:243
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
util-memcmp.h
DetectEngineCtx_::sgh_array_size
uint32_t sgh_array_size
Definition: detect.h:1069
SigGroupHeadInitData_::pkt_mpms
MpmCtx ** pkt_mpms
Definition: detect.h:1713
SignatureIsFileSha256Inspecting
int SignatureIsFileSha256Inspecting(const Signature *s)
Check if a signature contains the filesha256 keyword.
Definition: detect-engine-build.c:171
Signature_::next
struct Signature_ * next
Definition: detect.h:778
util-cidr.h
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:34
decode.h
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
SigGroupHeadBuildMatchArray
int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t max_idx)
Create an array with all the internal ids of the sigs that this sig group head will check for.
Definition: detect-engine-siggroup.c:531
SigGroupHeadInitData_::sig_cnt
SigIntId sig_cnt
Definition: detect.h:1723
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
util-error.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectEngineThreadCtx_
Definition: detect.h:1316
SigGroupHeadInitData_::tx_engines
PrefilterEngineList * tx_engines
Definition: detect.h:1718
DetectEngineGetMaxSigId
#define DetectEngineGetMaxSigId(de_ctx)
Definition: detect-engine.h:91
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3660
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1747
SigGroupHeadInitData_::direction
uint32_t direction
Definition: detect.h:1708
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:322
PacketL4::L4Hdrs::icmpv4h
ICMPV4Hdr * icmpv4h
Definition: decode.h:483
SCReturn
#define SCReturn
Definition: util-debug.h:286
ICMPV4Hdr_::type
uint8_t type
Definition: decode-icmpv4.h:166
Packet_
Definition: decode.h:516
SCFreeAligned
#define SCFreeAligned(p)
Definition: util-mem.h:77
detect-engine-build.h
Packet_::l4
struct PacketL4 l4
Definition: decode.h:616
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:300
SigGroupHeadInitData_::max_sig_id
uint32_t max_sig_id
Definition: detect.h:1710
DetectEngineCtx_::sgh_array_cnt
uint32_t sgh_array_cnt
Definition: detect.h:1068
SigGroupHeadAppendSig
int SigGroupHeadAppendSig(const DetectEngineCtx *de_ctx, SigGroupHead **sgh, const Signature *s)
Add a Signature to a SigGroupHead.
Definition: detect-engine-siggroup.c:318
DetectEngineCtx_::sgh_array
struct SigGroupHead_ ** sgh_array
Definition: detect.h:1067
HashListTable_
Definition: util-hashlist.h:37
SigGroupHeadFree
void SigGroupHeadFree(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Free a SigGroupHead and its members.
Definition: detect-engine-siggroup.c:162
SigGroupHeadInitData_::app_mpms
MpmCtx ** app_mpms
Definition: detect.h:1712
SignatureIsFileSha1Inspecting
int SignatureIsFileSha1Inspecting(const Signature *s)
Check if a signature contains the filesha1 keyword.
Definition: detect-engine-build.c:155
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2300
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1332
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
SigGroupHeadInitData_::pkt_engines
PrefilterEngineList * pkt_engines
Definition: detect.h:1716
SigGroupHeadSetSigCnt
void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
Updates the SigGroupHead->sig_cnt with the total count of all the Signatures present in this SigGroup...
Definition: detect-engine-siggroup.c:445
th_v
ThreadVars * th_v
Definition: fuzz_dataset.c:29
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
suricata-common.h
SigGroupHeadStore
void SigGroupHeadStore(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-siggroup.c:108
SigGroupHeadInitData_::frame_engines
PrefilterEngineList * frame_engines
Definition: detect.h:1719
SigGroupHeadInitData_::payload_engines
PrefilterEngineList * payload_engines
Definition: detect.h:1717
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:87
SigGroupHeadInitData_::match_array
Signature ** match_array
Definition: detect.h:1726
SCMallocAligned
#define SCMallocAligned(size, align)
Definition: util-mem.h:68
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3905
SigGroupHeadInitData_::sig_size
uint32_t sig_size
Definition: detect.h:1705
PrefilterCleanupRuleGroup
void PrefilterCleanupRuleGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-prefilter.c:531
ICMPV4Hdr_::code
uint8_t code
Definition: decode-icmpv4.h:167
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:1005
SigGroupHeadHashFree
void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by SigGroupHeadHashInit() function.
Definition: detect-engine-siggroup.c:298
SigGroupHeadHashAdd
int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Adds a SigGroupHead to the detection engine context SigGroupHead hash table.
Definition: detect-engine-siggroup.c:265
util-validate.h
SigGroupHeadInitData_
Definition: detect.h:1701
SigGroupHeadHashLookup
SigGroupHead * SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Used to lookup a SigGroupHead hash from the detection engine context SigGroupHead hash table.
Definition: detect-engine-siggroup.c:282
Signature_::iid
SigIntId iid
Definition: detect.h:704
SignatureIsFilestoring
int SignatureIsFilestoring(const Signature *s)
Check if a signature contains the filestore keyword.
Definition: detect-engine-build.c:101
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SigGroupHeadInitData_::post_rule_match_engines
PrefilterEngineList * post_rule_match_engines
Definition: detect.h:1720
Signature_::id
uint32_t id
Definition: detect.h:741
detect-parse.h
src
uint16_t src
Definition: app-layer-dnp3.h:5
Signature_
Signature container.
Definition: detect.h:692
SigGroupHeadInitDataFree
void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid)
Definition: detect-engine-siggroup.c:59
SigGroupHeadContainsSigId
int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid)
Check if a SigGroupHead contains a Signature, whose sid is sent as an argument.
Definition: detect-engine-siggroup.c:616
SignatureIsFileMd5Inspecting
int SignatureIsFileMd5Inspecting(const Signature *s)
Check if a signature contains the filemd5 keyword.
Definition: detect-engine-build.c:139
PacketL4::hdrs
union PacketL4::L4Hdrs hdrs
SigGroupHeadInitData_::protos
uint8_t protos[256]
Definition: detect.h:1707
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2873
app-layer-protos.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:1014
Packet_::dst
Address dst
Definition: decode.h:521
detect-uricontent.h
dst
uint16_t dst
Definition: app-layer-dnp3.h:4
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SIG_GROUP_HEAD_HAVEFILESHA256
#define SIG_GROUP_HEAD_HAVEFILESHA256
Definition: detect.h:1581
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
SignatureIsFilemagicInspecting
int SignatureIsFilemagicInspecting(const Signature *s)
Check if a signature contains the filemagic keyword.
Definition: detect-engine-build.c:120
SigGroupHead_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1736
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1428
flow-var.h
PrefilterFreeEnginesList
void PrefilterFreeEnginesList(PrefilterEngineList *list)
Definition: detect-engine-prefilter.c:503
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:289
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
detect-engine-address.h
SigMatchSignaturesGetSgh
const SigGroupHead * SigMatchSignaturesGetSgh(const DetectEngineCtx *de_ctx, const Packet *p)
Get the SigGroupHead for a packet.
Definition: detect.c:293
SigGroupHeadCopySigs
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
Copies the bitarray holding the sids from the source SigGroupHead to the destination SigGroupHead.
Definition: detect-engine-siggroup.c:389
SigGroupHeadClearSigs
int SigGroupHeadClearSigs(SigGroupHead *)
Clears the bitarray holding the sids for this SigGroupHead.
Definition: detect-engine-siggroup.c:347
SigGroupHeadInitData_::frame_mpms
MpmCtx ** frame_mpms
Definition: detect.h:1714
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:453