1 /* Copyright (C) 2007-2013 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-address.h"
37 #include "detect-engine-mpm.h"
38 #include "detect-engine-siggroup.h"
39 #include "detect-engine-prefilter.h"
40 
41 #include "detect-content.h"
42 #include "detect-uricontent.h"
43 #include "detect-tcp-flags.h"
44 
45 #include "util-hash.h"
46 #include "util-hashlist.h"
47 
48 #include "util-error.h"
49 #include "util-debug.h"
50 #include "util-cidr.h"
51 #include "util-unittest.h"
52 #include "util-unittest-helper.h"
53 #include "util-memcmp.h"
54 
55 /* prototypes */
56 int SigGroupHeadClearSigs(SigGroupHead *);
57 
SigGroupHeadInitDataFree(SigGroupHeadInitData * sghid)58 void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid)
59 {
60     if (sghid->sig_array != NULL) {
61         SCFree(sghid->sig_array);
62         sghid->sig_array = NULL;
63     }
64     if (sghid->app_mpms != NULL) {
65         SCFree(sghid->app_mpms);
66     }
67     if (sghid->pkt_mpms != NULL) {
68         SCFree(sghid->pkt_mpms);
69     }
70 
71     PrefilterFreeEnginesList(sghid->tx_engines);
72     PrefilterFreeEnginesList(sghid->pkt_engines);
73     PrefilterFreeEnginesList(sghid->payload_engines);
74 
75     SCFree(sghid);
76 }
77 
SigGroupHeadInitDataAlloc(uint32_t size)78 static SigGroupHeadInitData *SigGroupHeadInitDataAlloc(uint32_t size)
79 {
80     SigGroupHeadInitData *sghid = SCMalloc(sizeof(SigGroupHeadInitData));
81     if (unlikely(sghid == NULL))
82         return NULL;
83 
84     memset(sghid, 0x00, sizeof(SigGroupHeadInitData));
85 
86     /* initialize the signature bitarray */
87     sghid->sig_size = size;
88     if ( (sghid->sig_array = SCMalloc(sghid->sig_size)) == NULL)
89         goto error;
90 
91     memset(sghid->sig_array, 0, sghid->sig_size);
92 
93     return sghid;
94 error:
95     SigGroupHeadInitDataFree(sghid);
96     return NULL;
97 }
98 
SigGroupHeadStore(DetectEngineCtx * de_ctx,SigGroupHead * sgh)99 void SigGroupHeadStore(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
100 {
101     void *ptmp;
102     //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);
103     if (de_ctx->sgh_array_cnt < de_ctx->sgh_array_size) {
104         de_ctx->sgh_array[de_ctx->sgh_array_cnt] = sgh;
105     } else {
106         int increase = 16;
107         ptmp = SCRealloc(de_ctx->sgh_array,
108                          sizeof(SigGroupHead *) * (increase + de_ctx->sgh_array_size));
109         if (ptmp == NULL) {
110             SCFree(de_ctx->sgh_array);
111             de_ctx->sgh_array = NULL;
112             return;
113         }
114         de_ctx->sgh_array = ptmp;
115 
116         de_ctx->sgh_array_size += increase;
117         de_ctx->sgh_array[de_ctx->sgh_array_cnt] = sgh;
118     }
119     de_ctx->sgh_array_cnt++;
120 }
121 
122 /**
123  * \brief Alloc a SigGroupHead and its signature bit_array.
124  *
125  * \param size Size of the sig_array that has to be created for this
126  *             SigGroupHead.
127  *
128  * \retval sgh Pointer to the newly init SigGroupHead on success; or NULL in
129  *             case of error.
130  */
SigGroupHeadAlloc(const DetectEngineCtx * de_ctx,uint32_t size)131 static SigGroupHead *SigGroupHeadAlloc(const DetectEngineCtx *de_ctx, uint32_t size)
132 {
133     SigGroupHead *sgh = SCMalloc(sizeof(SigGroupHead));
134     if (unlikely(sgh == NULL))
135         return NULL;
136     memset(sgh, 0, sizeof(SigGroupHead));
137 
138     sgh->init = SigGroupHeadInitDataAlloc(size);
139     if (sgh->init == NULL)
140         goto error;
141 
142     return sgh;
143 
144 error:
145     SigGroupHeadFree(de_ctx, sgh);
146     return NULL;
147 }
148 
149 /**
150  * \brief Free a SigGroupHead and its members.
151  *
152  * \param sgh Pointer to the SigGroupHead that has to be freed.
153  */
SigGroupHeadFree(const DetectEngineCtx * de_ctx,SigGroupHead * sgh)154 void SigGroupHeadFree(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
155 {
156     if (sgh == NULL)
157         return;
158 
159     SCLogDebug("sgh %p", sgh);
160 
161     if (sgh->match_array != NULL) {
162         SCFree(sgh->match_array);
163         sgh->match_array = NULL;
164     }
165 
166     if (sgh->non_pf_other_store_array != NULL) {
167         SCFree(sgh->non_pf_other_store_array);
168         sgh->non_pf_other_store_array = NULL;
169         sgh->non_pf_other_store_cnt = 0;
170     }
171 
172     if (sgh->non_pf_syn_store_array != NULL) {
173         SCFree(sgh->non_pf_syn_store_array);
174         sgh->non_pf_syn_store_array = NULL;
175         sgh->non_pf_syn_store_cnt = 0;
176     }
177 
178     sgh->sig_cnt = 0;
179 
180     if (sgh->init != NULL) {
181         SigGroupHeadInitDataFree(sgh->init);
182         sgh->init = NULL;
183     }
184 
185     PrefilterCleanupRuleGroup(de_ctx, sgh);
186     SCFree(sgh);
187 
188     return;
189 }
190 
191 /**
192  * \brief The hash function to be the used by the hash table -
193  *        DetectEngineCtx->sgh_hash_table.
194  *
195  * \param ht      Pointer to the hash table.
196  * \param data    Pointer to the SigGroupHead.
197  * \param datalen Not used in our case.
198  *
199  * \retval hash The generated hash value.
200  */
SigGroupHeadHashFunc(HashListTable * ht,void * data,uint16_t datalen)201 static uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen)
202 {
203     SigGroupHead *sgh = (SigGroupHead *)data;
204     uint32_t hash = 0;
205     uint32_t b = 0;
206 
207     SCLogDebug("hashing sgh %p", sgh);
208 
209     for (b = 0; b < sgh->init->sig_size; b++)
210         hash += sgh->init->sig_array[b];
211 
212     hash %= ht->array_size;
213     SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->init->sig_size);
214     return hash;
215 }
216 
217 /**
218  * \brief The Compare function to be used by the SigGroupHead hash table -
219  *        DetectEngineCtx->sgh_hash_table.
220  *
221  * \param data1 Pointer to the first SigGroupHead.
222  * \param len1  Not used.
223  * \param data2 Pointer to the second SigGroupHead.
224  * \param len2  Not used.
225  *
226  * \retval 1 If the 2 SigGroupHeads sent as args match.
227  * \retval 0 If the 2 SigGroupHeads sent as args do not match.
228  */
SigGroupHeadCompareFunc(void * data1,uint16_t len1,void * data2,uint16_t len2)229 static char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2,
230                              uint16_t len2)
231 {
232     SigGroupHead *sgh1 = (SigGroupHead *)data1;
233     SigGroupHead *sgh2 = (SigGroupHead *)data2;
234 
235     if (data1 == NULL || data2 == NULL)
236         return 0;
237 
238     if (sgh1->init->sig_size != sgh2->init->sig_size)
239         return 0;
240 
241     if (SCMemcmp(sgh1->init->sig_array, sgh2->init->sig_array, sgh1->init->sig_size) != 0)
242         return 0;
243 
244     return 1;
245 }
246 
247 /**
248  * \brief Initializes the hash table in the detection engine context to hold the
249  *        SigGroupHeads.
250  *
251  * \param de_ctx Pointer to the detection engine context.
252  *
253  * \retval  0 On success.
254  * \retval -1 On failure.
255  */
SigGroupHeadHashInit(DetectEngineCtx * de_ctx)256 int SigGroupHeadHashInit(DetectEngineCtx *de_ctx)
257 {
258     de_ctx->sgh_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc,
259                                                SigGroupHeadCompareFunc, NULL);
260     if (de_ctx->sgh_hash_table == NULL)
261         goto error;
262 
263     return 0;
264 
265 error:
266     return -1;
267 }
268 
269 /**
270  * \brief Adds a SigGroupHead to the detection engine context SigGroupHead
271  *        hash table.
272  *
273  * \param de_ctx Pointer to the detection engine context.
274  * \param sgh    Pointer to the SigGroupHead.
275  *
276  * \retval ret 0 on Successfully adding the SigGroupHead; -1 on failure.
277  */
SigGroupHeadHashAdd(DetectEngineCtx * de_ctx,SigGroupHead * sgh)278 int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
279 {
280     int ret = HashListTableAdd(de_ctx->sgh_hash_table, (void *)sgh, 0);
281 
282     return ret;
283 }
284 
SigGroupHeadHashRemove(DetectEngineCtx * de_ctx,SigGroupHead * sgh)285 int SigGroupHeadHashRemove(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
286 {
287     return HashListTableRemove(de_ctx->sgh_hash_table, (void *)sgh, 0);
288 }
289 
290 /**
291  * \brief Used to lookup a SigGroupHead hash from the detection engine context
292  *        SigGroupHead hash table.
293  *
294  * \param de_ctx Pointer to the detection engine context.
295  * \param sgh    Pointer to the SigGroupHead.
296  *
297  * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
298  *              found in the hash table; NULL on failure.
299  */
SigGroupHeadHashLookup(DetectEngineCtx * de_ctx,SigGroupHead * sgh)300 SigGroupHead *SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
301 {
302     SCEnter();
303 
304     SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_hash_table,
305                                              (void *)sgh, 0);
306 
307     SCReturnPtr(rsgh, "SigGroupHead");
308 }
309 
310 /**
311  * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
312  *        SigGroupHeadHashInit() function.
313  *
314  * \param de_ctx Pointer to the detection engine context.
315  */
SigGroupHeadHashFree(DetectEngineCtx * de_ctx)316 void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
317 {
318     if (de_ctx->sgh_hash_table == NULL)
319         return;
320 
321     HashListTableFree(de_ctx->sgh_hash_table);
322     de_ctx->sgh_hash_table = NULL;
323 
324     return;
325 }
326 
327 /**
328  * \brief Add a Signature to a SigGroupHead.
329  *
330  * \param de_ctx Pointer to the detection engine context.
331  * \param sgh    Pointer to a SigGroupHead.  Can be NULL also.
332  * \param s      Pointer to the Signature that has to be added to the
333  *               SigGroupHead.
334  *
335  * \retval  0 On success.
336  * \retval -1 On failure.
337  */
SigGroupHeadAppendSig(const DetectEngineCtx * de_ctx,SigGroupHead ** sgh,const Signature * s)338 int SigGroupHeadAppendSig(const DetectEngineCtx *de_ctx, SigGroupHead **sgh,
339                           const Signature *s)
340 {
341     if (de_ctx == NULL)
342         return 0;
343 
344     /* see if we have a head already */
345     if (*sgh == NULL) {
346         *sgh = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
347         if (*sgh == NULL)
348             goto error;
349     }
350 
351     /* enable the sig in the bitarray */
352     (*sgh)->init->sig_array[s->num / 8] |= 1 << (s->num % 8);
353 
354     return 0;
355 
356 error:
357     return -1;
358 }
359 
360 /**
361  * \brief Clears the bitarray holding the sids for this SigGroupHead.
362  *
363  * \param sgh Pointer to the SigGroupHead.
364  *
365  * \retval 0 Always.
366  */
SigGroupHeadClearSigs(SigGroupHead * sgh)367 int SigGroupHeadClearSigs(SigGroupHead *sgh)
368 {
369     if (sgh == NULL)
370         return 0;
371 
372     if (sgh->init->sig_array != NULL)
373         memset(sgh->init->sig_array, 0, sgh->init->sig_size);
374 
375     sgh->sig_cnt = 0;
376 
377     return 0;
378 }
379 
380 /**
381  * \brief Copies the bitarray holding the sids from the source SigGroupHead to
382  *        the destination SigGroupHead.
383  *
384  * \param de_ctx Pointer to the detection engine context.
385  * \param src    Pointer to the source SigGroupHead.
386  * \param dst    Pointer to the destination SigGroupHead.
387  *
388  * \retval  0 On success.
389  * \retval -1 On failure.
390  */
SigGroupHeadCopySigs(DetectEngineCtx * de_ctx,SigGroupHead * src,SigGroupHead ** dst)391 int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
392 {
393     uint32_t idx = 0;
394 
395     if (src == NULL || de_ctx == NULL)
396         return 0;
397 
398     if (*dst == NULL) {
399         *dst = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
400         if (*dst == NULL)
401             goto error;
402     }
403 
404     /* do the copy */
405     for (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 
408     if (src->init->whitelist)
409         (*dst)->init->whitelist = MAX((*dst)->init->whitelist, src->init->whitelist);
410 
411     return 0;
412 
413 error:
414     return -1;
415 }
416 
417 /**
418  * \brief Updates the SigGroupHead->sig_cnt with the total count of all the
419  *        Signatures present in this SigGroupHead.
420  *
421  * \param sgh     Pointer to the SigGroupHead.
422  * \param max_idx Maximum sid of the all the Signatures present in this
423  *                SigGroupHead.
424  */
SigGroupHeadSetSigCnt(SigGroupHead * sgh,uint32_t max_idx)425 void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
426 {
427     uint32_t sig;
428 
429     sgh->sig_cnt = 0;
430     for (sig = 0; sig < max_idx + 1; sig++) {
431         if (sgh->init->sig_array[sig / 8] & (1 << (sig % 8)))
432             sgh->sig_cnt++;
433     }
434 
435     return;
436 }
437 
SigGroupHeadSetProtoAndDirection(SigGroupHead * sgh,uint8_t ipproto,int dir)438 void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh,
439                                       uint8_t ipproto, int dir)
440 {
441     if (sgh && sgh->init) {
442         SCLogDebug("setting proto %u and dir %d on sgh %p", ipproto, dir, sgh);
443         sgh->init->protos[ipproto] = 1;
444         sgh->init->direction |= dir;
445     }
446 }
447 
448 /**
449  * \brief Helper function used to print the list of sids for the Signatures
450  *        present in this SigGroupHead.
451  *
452  * \param de_ctx Pointer to the detection engine context.
453  * \param sgh    Pointer to the SigGroupHead.
454  */
SigGroupHeadPrintSigs(DetectEngineCtx * de_ctx,SigGroupHead * sgh)455 void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
456 {
457     SCEnter();
458 
459     if (sgh == NULL) {
460         SCReturn;
461     }
462 
463     uint32_t u;
464 
465     SCLogDebug("The Signatures present in this SigGroupHead are: ");
466     for (u = 0; u < (sgh->init->sig_size * 8); u++) {
467         if (sgh->init->sig_array[u / 8] & (1 << (u % 8))) {
468             SCLogDebug("%" PRIu32, u);
469             printf("s->num %"PRIu32" ", u);
470         }
471     }
472 
473     SCReturn;
474 }
475 
476 /**
477  * \brief Create an array with all the internal ids of the sigs that this
478  *        sig group head will check for.
479  *
480  * \param de_ctx  Pointer to the detection engine context.
481  * \param sgh     Pointer to the SigGroupHead.
482  * \param max_idx The maximum value of the sid in the SigGroupHead arg.
483  *
484  * \retval  0 success
485  * \retval -1 error
486  */
SigGroupHeadBuildMatchArray(DetectEngineCtx * de_ctx,SigGroupHead * sgh,uint32_t max_idx)487 int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
488                                 uint32_t max_idx)
489 {
490     Signature *s = NULL;
491     uint32_t idx = 0;
492     uint32_t sig = 0;
493 
494     if (sgh == NULL)
495         return 0;
496 
497     BUG_ON(sgh->match_array != NULL);
498 
499     sgh->match_array = SCMalloc(sgh->sig_cnt * sizeof(Signature *));
500     if (sgh->match_array == NULL)
501         return -1;
502 
503     memset(sgh->match_array,0, sgh->sig_cnt * sizeof(Signature *));
504 
505     for (sig = 0; sig < max_idx + 1; sig++) {
506         if (!(sgh->init->sig_array[(sig / 8)] & (1 << (sig % 8))) )
507             continue;
508 
509         s = de_ctx->sig_array[sig];
510         if (s == NULL)
511             continue;
512 
513         sgh->match_array[idx] = s;
514         idx++;
515     }
516 
517     return 0;
518 }
519 
520 /**
521  *  \brief Set the need magic flag in the sgh.
522  *
523  *  \param de_ctx detection engine ctx for the signatures
524  *  \param sgh sig group head to set the flag in
525  */
SigGroupHeadSetFilemagicFlag(DetectEngineCtx * de_ctx,SigGroupHead * sgh)526 void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
527 {
528 #ifdef HAVE_MAGIC
529     Signature *s = NULL;
530     uint32_t sig = 0;
531 
532     if (sgh == NULL)
533         return;
534 
535     for (sig = 0; sig < sgh->sig_cnt; sig++) {
536         s = sgh->match_array[sig];
537         if (s == NULL)
538             continue;
539 
540         if (SignatureIsFilemagicInspecting(s)) {
541             sgh->flags |= SIG_GROUP_HEAD_HAVEFILEMAGIC;
542             break;
543         }
544     }
545 #endif
546     return;
547 }
548 
549 /**
550  *  \brief Set the need size flag in the sgh.
551  *
552  *  \param de_ctx detection engine ctx for the signatures
553  *  \param sgh sig group head to set the flag in
554  */
SigGroupHeadSetFilesizeFlag(DetectEngineCtx * de_ctx,SigGroupHead * sgh)555 void SigGroupHeadSetFilesizeFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
556 {
557     Signature *s = NULL;
558     uint32_t sig = 0;
559 
560     if (sgh == NULL)
561         return;
562 
563     for (sig = 0; sig < sgh->sig_cnt; sig++) {
564         s = sgh->match_array[sig];
565         if (s == NULL)
566             continue;
567 
568         if (SignatureIsFilesizeInspecting(s)) {
569             sgh->flags |= SIG_GROUP_HEAD_HAVEFILESIZE;
570             break;
571         }
572     }
573 
574     return;
575 }
576 
577 /**
578  *  \brief Set the need hash flag in the sgh.
579  *
580  *  \param de_ctx detection engine ctx for the signatures
581  *  \param sgh sig group head to set the flag in
582  */
SigGroupHeadSetFileHashFlag(DetectEngineCtx * de_ctx,SigGroupHead * sgh)583 void SigGroupHeadSetFileHashFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
584 {
585     Signature *s = NULL;
586     uint32_t sig = 0;
587 
588     if (sgh == NULL)
589         return;
590 
591     for (sig = 0; sig < sgh->sig_cnt; sig++) {
592         s = sgh->match_array[sig];
593         if (s == NULL)
594             continue;
595 
596         if (SignatureIsFileMd5Inspecting(s)) {
597             sgh->flags |= SIG_GROUP_HEAD_HAVEFILEMD5;
598             SCLogDebug("sgh %p has filemd5", sgh);
599             break;
600         }
601 
602         if (SignatureIsFileSha1Inspecting(s)) {
603             sgh->flags |= SIG_GROUP_HEAD_HAVEFILESHA1;
604             SCLogDebug("sgh %p has filesha1", sgh);
605             break;
606         }
607 
608         if (SignatureIsFileSha256Inspecting(s)) {
609             sgh->flags |= SIG_GROUP_HEAD_HAVEFILESHA256;
610             SCLogDebug("sgh %p has filesha256", sgh);
611             break;
612         }
613     }
614 
615     return;
616 }
617 
618 /**
619  *  \brief Set the filestore_cnt in the sgh.
620  *
621  *  \param de_ctx detection engine ctx for the signatures
622  *  \param sgh sig group head to set the counter in
623  */
SigGroupHeadSetFilestoreCount(DetectEngineCtx * de_ctx,SigGroupHead * sgh)624 void SigGroupHeadSetFilestoreCount(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
625 {
626     Signature *s = NULL;
627     uint32_t sig = 0;
628 
629     if (sgh == NULL)
630         return;
631 
632     for (sig = 0; sig < sgh->sig_cnt; sig++) {
633         s = sgh->match_array[sig];
634         if (s == NULL)
635             continue;
636 
637         if (SignatureIsFilestoring(s)) {
638             sgh->filestore_cnt++;
639         }
640     }
641 
642     return;
643 }
644 
645 /** \brief build an array of rule id's for sigs with no prefilter
646  *  Also updated de_ctx::non_pf_store_cnt_max to track the highest cnt
647  */
SigGroupHeadBuildNonPrefilterArray(DetectEngineCtx * de_ctx,SigGroupHead * sgh)648 int SigGroupHeadBuildNonPrefilterArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
649 {
650     Signature *s = NULL;
651     uint32_t sig = 0;
652     uint32_t non_pf = 0;
653     uint32_t non_pf_syn = 0;
654 
655     if (sgh == NULL)
656         return 0;
657 
658     BUG_ON(sgh->non_pf_other_store_array != NULL);
659 
660     for (sig = 0; sig < sgh->sig_cnt; sig++) {
661         s = sgh->match_array[sig];
662         if (s == NULL)
663             continue;
664 
665         if (!(s->flags & SIG_FLAG_PREFILTER) || (s->flags & SIG_FLAG_MPM_NEG)) {
666             if (!(DetectFlagsSignatureNeedsSynPackets(s))) {
667                 non_pf++;
668             }
669             non_pf_syn++;
670         }
671     }
672 
673     if (non_pf == 0 && non_pf_syn == 0) {
674         sgh->non_pf_other_store_array = NULL;
675         sgh->non_pf_syn_store_array = NULL;
676         return 0;
677     }
678 
679     if (non_pf > 0) {
680         sgh->non_pf_other_store_array = SCMalloc(non_pf * sizeof(SignatureNonPrefilterStore));
681         BUG_ON(sgh->non_pf_other_store_array == NULL);
682         memset(sgh->non_pf_other_store_array, 0, non_pf * sizeof(SignatureNonPrefilterStore));
683     }
684 
685     if (non_pf_syn > 0) {
686         sgh->non_pf_syn_store_array = SCMalloc(non_pf_syn * sizeof(SignatureNonPrefilterStore));
687         BUG_ON(sgh->non_pf_syn_store_array == NULL);
688         memset(sgh->non_pf_syn_store_array, 0, non_pf_syn * sizeof(SignatureNonPrefilterStore));
689     }
690 
691     for (sig = 0; sig < sgh->sig_cnt; sig++) {
692         s = sgh->match_array[sig];
693         if (s == NULL)
694             continue;
695 
696         if (!(s->flags & SIG_FLAG_PREFILTER) || (s->flags & SIG_FLAG_MPM_NEG)) {
697             if (!(DetectFlagsSignatureNeedsSynPackets(s))) {
698                 BUG_ON(sgh->non_pf_other_store_cnt >= non_pf);
699                 BUG_ON(sgh->non_pf_other_store_array == NULL);
700                 sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].id = s->num;
701                 sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].mask = s->mask;
702                 sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].alproto = s->alproto;
703                 sgh->non_pf_other_store_cnt++;
704             }
705 
706             BUG_ON(sgh->non_pf_syn_store_cnt >= non_pf_syn);
707             BUG_ON(sgh->non_pf_syn_store_array == NULL);
708             sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].id = s->num;
709             sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].mask = s->mask;
710             sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].alproto = s->alproto;
711             sgh->non_pf_syn_store_cnt++;
712         }
713     }
714 
715     /* track highest cnt for any sgh in our de_ctx */
716     uint32_t max = MAX(sgh->non_pf_other_store_cnt, sgh->non_pf_syn_store_cnt);
717     if (max > de_ctx->non_pf_store_cnt_max)
718         de_ctx->non_pf_store_cnt_max = max;
719 
720     return 0;
721 }
722 
723 /**
724  * \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an
725  *        argument.
726  *
727  * \param de_ctx Pointer to the detection engine context.
728  * \param sgh    Pointer to the SigGroupHead that has to be checked for the
729  *               presence of a Signature.
730  * \param sid    The Signature id(sid) that has to be checked in the SigGroupHead.
731  *
732  * \retval 1 On successfully finding the sid in the SigGroupHead.
733  * \retval 0 If the sid is not found in the SigGroupHead
734  */
SigGroupHeadContainsSigId(DetectEngineCtx * de_ctx,SigGroupHead * sgh,uint32_t sid)735 int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
736                               uint32_t sid)
737 {
738     SCEnter();
739 
740     uint32_t sig = 0;
741     Signature *s = NULL;
742     uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx);
743 
744     if (sgh == NULL) {
745         SCReturnInt(0);
746     }
747 
748     for (sig = 0; sig < max_sid; sig++) {
749         if (sgh->init->sig_array == NULL) {
750             SCReturnInt(0);
751         }
752 
753         /* Check if the SigGroupHead has an entry for the sid */
754         if ( !(sgh->init->sig_array[sig / 8] & (1 << (sig % 8))) )
755             continue;
756 
757         /* If we have reached here, we have an entry for sid in the SigGrouHead.
758          * Retrieve the Signature from the detection engine context */
759         s = de_ctx->sig_array[sig];
760         if (s == NULL)
761             continue;
762 
763         /* If the retrieved Signature matches the sid arg, we have a match */
764         if (s->id == sid) {
765             SCReturnInt(1);
766         }
767     }
768 
769     SCReturnInt(0);
770 }
771 
772 /*----------------------------------Unittests---------------------------------*/
773 
774 #ifdef UNITTESTS
775 
776 int SigAddressPrepareStage1(DetectEngineCtx *);
777 
778 /**
779  * \test Check if a SigGroupHead hash table is properly allocated and
780  *       deallocated when calling SigGroupHeadHashInit() and
781  *       SigGroupHeadHashFree() respectively.
782  */
SigGroupHeadTest03(void)783 static int SigGroupHeadTest03(void)
784 {
785     int result = 1;
786 
787     DetectEngineCtx de_ctx;
788 
789     SigGroupHeadHashInit(&de_ctx);
790 
791     result &= (de_ctx.sgh_hash_table != NULL);
792 
793     SigGroupHeadHashFree(&de_ctx);
794 
795     result &= (de_ctx.sgh_hash_table == NULL);
796 
797     return result;
798 }
799 
800 /**
801  * \test Check if a SigGroupHeadAppendSig() correctly appends a sid to a
802  *       SigGroupHead() and SigGroupHeadContainsSigId() correctly indicates
803  *       the presence of a sid.
804  */
SigGroupHeadTest06(void)805 static int SigGroupHeadTest06(void)
806 {
807     int result = 1;
808     SigGroupHead *sh = NULL;
809     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
810     Signature *prev_sig = NULL;
811 
812     if (de_ctx == NULL)
813         return 0;
814 
815     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
816                                "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
817                                "content:\"test2\"; content:\"test3\"; sid:1;)");
818     if (de_ctx->sig_list == NULL) {
819         result = 0;
820         goto end;
821     }
822     prev_sig = de_ctx->sig_list;
823 
824     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
825                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
826                              "content:\"test2\"; content:\"test3\"; sid:2;)");
827     if (prev_sig->next == NULL) {
828         result = 0;
829         goto end;
830     }
831     prev_sig = prev_sig->next;
832 
833     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
834                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
835                              "content:\"test2\"; content:\"test3\"; sid:3;)");
836     if (prev_sig->next == NULL) {
837         result = 0;
838         goto end;
839     }
840     prev_sig = prev_sig->next;
841 
842     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
843                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
844                              "content:\"test2\"; content:\"test3\"; sid:4;)");
845     if (prev_sig->next == NULL) {
846         result = 0;
847         goto end;
848     }
849     prev_sig = prev_sig->next;
850 
851     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
852                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
853                              "content:\"test2\"; content:\"test3\"; sid:5;)");
854     if (prev_sig->next == NULL) {
855         result = 0;
856         goto end;
857     }
858     prev_sig = prev_sig->next;
859 
860     SigAddressPrepareStage1(de_ctx);
861 
862     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
863     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
864     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
865 
866     SigGroupHeadSetSigCnt(sh, 4);
867 
868     result &= (sh->sig_cnt == 3);
869     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 1);
870     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
871     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 1);
872     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
873     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 5) == 1);
874 
875     SigGroupHeadFree(de_ctx, sh);
876 
877  end:
878     SigCleanSignatures(de_ctx);
879     DetectEngineCtxFree(de_ctx);
880     return result;
881 }
882 
883 /**
884  * \test Check if a SigGroupHeadAppendSig(), correctly appends a sid to a
885  *       SigGroupHead() and SigGroupHeadContainsSigId(), correctly indicates
886  *       the presence of a sid and SigGroupHeadClearSigs(), correctly clears
887  *       the SigGroupHead->sig_array and SigGroupHead->sig_cnt.
888  */
SigGroupHeadTest07(void)889 static int SigGroupHeadTest07(void)
890 {
891     int result = 1;
892     SigGroupHead *sh = NULL;
893     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
894     Signature *prev_sig = NULL;
895 
896     if (de_ctx == NULL)
897         return 0;
898 
899     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
900                                "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
901                                "content:\"test2\"; content:\"test3\"; sid:1;)");
902     if (de_ctx->sig_list == NULL) {
903         result = 0;
904         goto end;
905     }
906     prev_sig = de_ctx->sig_list;
907 
908     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
909                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
910                              "content:\"test2\"; content:\"test3\"; sid:2;)");
911     if (prev_sig->next == NULL) {
912         result = 0;
913         goto end;
914     }
915     prev_sig = prev_sig->next;
916 
917     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
918                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
919                              "content:\"test2\"; content:\"test3\"; sid:3;)");
920     if (prev_sig->next == NULL) {
921         result = 0;
922         goto end;
923     }
924     prev_sig = prev_sig->next;
925 
926     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
927                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
928                              "content:\"test2\"; content:\"test3\"; sid:4;)");
929     if (prev_sig->next == NULL) {
930         result = 0;
931         goto end;
932     }
933     prev_sig = prev_sig->next;
934 
935     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
936                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
937                              "content:\"test2\"; content:\"test3\"; sid:5;)");
938     if (prev_sig->next == NULL) {
939         result = 0;
940         goto end;
941     }
942     prev_sig = prev_sig->next;
943 
944     SigAddressPrepareStage1(de_ctx);
945 
946     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
947     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
948     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
949 
950     SigGroupHeadSetSigCnt(sh, 4);
951 
952     result &= (sh->sig_cnt == 3);
953     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 1);
954     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
955     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 1);
956     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
957     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 5) == 1);
958 
959     SigGroupHeadClearSigs(sh);
960 
961     result &= (sh->sig_cnt == 0);
962     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0);
963     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
964     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0);
965     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
966     result &= (SigGroupHeadContainsSigId(de_ctx, sh, 5) == 0);
967 
968     SigGroupHeadFree(de_ctx, sh);
969 
970  end:
971     SigCleanSignatures(de_ctx);
972     DetectEngineCtxFree(de_ctx);
973     return result;
974 }
975 
976 /**
977  * \test Check if SigGroupHeadCopySigs(), correctly copies the sig_array from
978  *       the source to the destination SigGroupHead.
979  */
SigGroupHeadTest08(void)980 static int SigGroupHeadTest08(void)
981 {
982     int result = 1;
983     SigGroupHead *src_sh = NULL;
984     SigGroupHead *dst_sh = NULL;
985     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
986     Signature *prev_sig = NULL;
987 
988     if (de_ctx == NULL)
989         return 0;
990 
991     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
992                                "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
993                                "content:\"test2\"; content:\"test3\"; sid:1;)");
994     if (de_ctx->sig_list == NULL) {
995         result = 0;
996         goto end;
997     }
998     prev_sig = de_ctx->sig_list;
999 
1000     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1001                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1002                              "content:\"test2\"; content:\"test3\"; sid:2;)");
1003     if (prev_sig->next == NULL) {
1004         result = 0;
1005         goto end;
1006     }
1007     prev_sig = prev_sig->next;
1008 
1009     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1010                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1011                              "content:\"test2\"; content:\"test3\"; sid:3;)");
1012     if (prev_sig->next == NULL) {
1013         result = 0;
1014         goto end;
1015     }
1016     prev_sig = prev_sig->next;
1017 
1018     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1019                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1020                              "content:\"test2\"; content:\"test3\"; sid:4;)");
1021     if (prev_sig->next == NULL) {
1022         result = 0;
1023         goto end;
1024     }
1025     prev_sig = prev_sig->next;
1026 
1027     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1028                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1029                              "content:\"test2\"; content:\"test3\"; sid:5;)");
1030     if (prev_sig->next == NULL) {
1031         result = 0;
1032         goto end;
1033     }
1034     prev_sig = prev_sig->next;
1035 
1036     SigAddressPrepareStage1(de_ctx);
1037 
1038     SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list);
1039     SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next);
1040     SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next->next->next);
1041 
1042     SigGroupHeadSetSigCnt(src_sh, 4);
1043 
1044     result &= (src_sh->sig_cnt == 3);
1045     result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 1) == 1);
1046     result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 2) == 0);
1047     result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 3) == 1);
1048     result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 4) == 0);
1049     result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 5) == 1);
1050 
1051     SigGroupHeadCopySigs(de_ctx, src_sh, &dst_sh);
1052 
1053     SigGroupHeadSetSigCnt(dst_sh, 4);
1054 
1055     result &= (dst_sh->sig_cnt == 3);
1056     result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 1) == 1);
1057     result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 2) == 0);
1058     result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 3) == 1);
1059     result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 4) == 0);
1060     result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 5) == 1);
1061 
1062     SigGroupHeadFree(de_ctx, src_sh);
1063     SigGroupHeadFree(de_ctx, dst_sh);
1064 
1065  end:
1066     SigCleanSignatures(de_ctx);
1067     DetectEngineCtxFree(de_ctx);
1068     return result;
1069 }
1070 
1071 /**
1072  * \test Check if SigGroupHeadBuildMatchArray(), correctly updates the
1073  *       match array with the sids.
1074  */
SigGroupHeadTest09(void)1075 static int SigGroupHeadTest09(void)
1076 {
1077     int result = 1;
1078     SigGroupHead *sh = NULL;
1079     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1080     Signature *prev_sig = NULL;
1081 
1082     if (de_ctx == NULL)
1083         return 0;
1084 
1085     de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1086                                "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1087                                "content:\"test2\"; content:\"test3\"; sid:1;)");
1088     if (de_ctx->sig_list == NULL) {
1089         result = 0;
1090         goto end;
1091     }
1092     prev_sig = de_ctx->sig_list;
1093 
1094     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1095                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1096                              "content:\"test2\"; content:\"test3\"; sid:2;)");
1097     if (prev_sig->next == NULL) {
1098         result = 0;
1099         goto end;
1100     }
1101     prev_sig = prev_sig->next;
1102 
1103     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1104                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1105                              "content:\"test2\"; content:\"test3\"; sid:3;)");
1106     if (prev_sig->next == NULL) {
1107         result = 0;
1108         goto end;
1109     }
1110     prev_sig = prev_sig->next;
1111 
1112     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1113                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1114                              "content:\"test2\"; content:\"test3\"; sid:4;)");
1115     if (prev_sig->next == NULL) {
1116         result = 0;
1117         goto end;
1118     }
1119     prev_sig = prev_sig->next;
1120 
1121     prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
1122                              "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1123                              "content:\"test2\"; content:\"test3\"; sid:5;)");
1124     if (prev_sig->next == NULL) {
1125         result = 0;
1126         goto end;
1127     }
1128     prev_sig = prev_sig->next;
1129 
1130     SigAddressPrepareStage1(de_ctx);
1131 
1132     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
1133     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
1134     SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
1135 
1136     SigGroupHeadSetSigCnt(sh, 4);
1137     SigGroupHeadBuildMatchArray(de_ctx, sh, 4);
1138 
1139     result &= (sh->match_array[0] == de_ctx->sig_list);
1140     result &= (sh->match_array[1] == de_ctx->sig_list->next->next);
1141     result &= (sh->match_array[2] == de_ctx->sig_list->next->next->next->next);
1142 
1143     SigGroupHeadFree(de_ctx, sh);
1144 
1145  end:
1146     SigCleanSignatures(de_ctx);
1147     DetectEngineCtxFree(de_ctx);
1148     return result;
1149 }
1150 
1151 /**
1152  * \test ICMP(?) sig grouping bug.
1153  */
SigGroupHeadTest10(void)1154 static int SigGroupHeadTest10(void)
1155 {
1156     int result = 0;
1157     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1158     Signature *s = NULL;
1159     Packet *p = NULL;
1160     DetectEngineThreadCtx *det_ctx = NULL;
1161     ThreadVars th_v;
1162 
1163     memset(&th_v, 0, sizeof(ThreadVars));
1164 
1165     p = UTHBuildPacketSrcDst(NULL, 0, IPPROTO_ICMP, "192.168.1.1", "1.2.3.4");
1166     p->icmpv4h->type = 5;
1167     p->icmpv4h->code = 1;
1168 
1169     /* originally ip's were
1170     p.src.addr_data32[0] = 0xe08102d3;
1171     p.dst.addr_data32[0] = 0x3001a8c0;
1172     */
1173 
1174     if (de_ctx == NULL)
1175         return 0;
1176 
1177     s = DetectEngineAppendSig(de_ctx, "alert icmp 192.168.0.0/16 any -> any any (icode:>1; itype:11; sid:1; rev:1;)");
1178     if (s == NULL) {
1179         goto end;
1180     }
1181     s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> 192.168.0.0/16 any (icode:1; itype:5; sid:2; rev:1;)");
1182     if (s == NULL) {
1183         goto end;
1184     }
1185 
1186     SigGroupBuild(de_ctx);
1187     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1188 
1189     AddressDebugPrint(&p->dst);
1190 
1191     const SigGroupHead *sgh = SigMatchSignaturesGetSgh(de_ctx, p);
1192     if (sgh == NULL) {
1193         goto end;
1194     }
1195 
1196     result = 1;
1197 end:
1198     SigCleanSignatures(de_ctx);
1199     DetectEngineCtxFree(de_ctx);
1200     UTHFreePackets(&p, 1);
1201     return result;
1202 }
1203 #endif
1204 
SigGroupHeadRegisterTests(void)1205 void SigGroupHeadRegisterTests(void)
1206 {
1207 #ifdef UNITTESTS
1208     UtRegisterTest("SigGroupHeadTest03", SigGroupHeadTest03);
1209     UtRegisterTest("SigGroupHeadTest06", SigGroupHeadTest06);
1210     UtRegisterTest("SigGroupHeadTest07", SigGroupHeadTest07);
1211     UtRegisterTest("SigGroupHeadTest08", SigGroupHeadTest08);
1212     UtRegisterTest("SigGroupHeadTest09", SigGroupHeadTest09);
1213     UtRegisterTest("SigGroupHeadTest10", SigGroupHeadTest10);
1214 #endif
1215 }
1216