1 /* Copyright (C) 2007-2020 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 parser
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 
29 #include "detect.h"
30 #include "detect-engine.h"
31 #include "detect-engine-address.h"
32 #include "detect-engine-port.h"
33 #include "detect-engine-mpm.h"
34 #include "detect-engine-state.h"
35 
36 #include "detect-content.h"
37 #include "detect-pcre.h"
38 #include "detect-uricontent.h"
39 #include "detect-reference.h"
40 #include "detect-ipproto.h"
41 #include "detect-flow.h"
42 #include "detect-app-layer-protocol.h"
43 #include "detect-lua.h"
44 #include "detect-app-layer-event.h"
45 #include "detect-http-method.h"
46 
47 #include "pkt-var.h"
48 #include "host.h"
49 #include "util-profiling.h"
50 #include "decode.h"
51 
52 #include "flow.h"
53 
54 #include "util-rule-vars.h"
55 #include "conf.h"
56 #include "conf-yaml-loader.h"
57 
58 #include "app-layer.h"
59 #include "app-layer-protos.h"
60 #include "app-layer-parser.h"
61 #include "app-layer-htp.h"
62 
63 #include "util-classification-config.h"
64 #include "util-unittest.h"
65 #include "util-unittest-helper.h"
66 #include "util-debug.h"
67 #include "string.h"
68 #include "detect-parse.h"
69 #include "detect-engine-iponly.h"
70 #include "app-layer-detect-proto.h"
71 
72 /* Table with all SigMatch registrations */
73 SigTableElmt sigmatch_table[DETECT_TBLSIZE];
74 
75 extern int sc_set_caps;
76 
77 static void SigMatchTransferSigMatchAcrossLists(SigMatch *sm,
78         SigMatch **src_sm_list, SigMatch **src_sm_list_tail,
79         SigMatch **dst_sm_list, SigMatch **dst_sm_list_tail);
80 
81 /**
82  * \brief We use this as data to the hash table DetectEngineCtx->dup_sig_hash_table.
83  */
84 typedef struct SigDuplWrapper_ {
85     /* the signature we want to wrap */
86     Signature *s;
87     /* the signature right before the above signature in the det_ctx->sig_list */
88     Signature *s_prev;
89 } SigDuplWrapper;
90 
91 #define CONFIG_PARTS 8
92 
93 #define CONFIG_ACTION 0
94 #define CONFIG_PROTO  1
95 #define CONFIG_SRC    2
96 #define CONFIG_SP     3
97 #define CONFIG_DIREC  4
98 #define CONFIG_DST    5
99 #define CONFIG_DP     6
100 #define CONFIG_OPTS   7
101 
102 /** helper structure for sig parsing */
103 typedef struct SignatureParser_ {
104     char action[DETECT_MAX_RULE_SIZE];
105     char protocol[DETECT_MAX_RULE_SIZE];
106     char direction[DETECT_MAX_RULE_SIZE];
107     char src[DETECT_MAX_RULE_SIZE];
108     char dst[DETECT_MAX_RULE_SIZE];
109     char sp[DETECT_MAX_RULE_SIZE];
110     char dp[DETECT_MAX_RULE_SIZE];
111     char opts[DETECT_MAX_RULE_SIZE];
112 } SignatureParser;
113 
DetectListToHumanString(int list)114 const char *DetectListToHumanString(int list)
115 {
116 #define CASE_CODE_STRING(E, S)  case E: return S; break
117     switch (list) {
118         CASE_CODE_STRING(DETECT_SM_LIST_MATCH, "packet");
119         CASE_CODE_STRING(DETECT_SM_LIST_PMATCH, "payload");
120         CASE_CODE_STRING(DETECT_SM_LIST_TMATCH, "tag");
121         CASE_CODE_STRING(DETECT_SM_LIST_POSTMATCH, "postmatch");
122         CASE_CODE_STRING(DETECT_SM_LIST_SUPPRESS, "suppress");
123         CASE_CODE_STRING(DETECT_SM_LIST_THRESHOLD, "threshold");
124         CASE_CODE_STRING(DETECT_SM_LIST_MAX, "max (internal)");
125     }
126 #undef CASE_CODE_STRING
127     return "unknown";
128 }
129 
130 #define CASE_CODE(E)  case E: return #E
DetectListToString(int list)131 const char *DetectListToString(int list)
132 {
133     switch (list) {
134         CASE_CODE(DETECT_SM_LIST_MATCH);
135         CASE_CODE(DETECT_SM_LIST_PMATCH);
136         CASE_CODE(DETECT_SM_LIST_TMATCH);
137         CASE_CODE(DETECT_SM_LIST_POSTMATCH);
138         CASE_CODE(DETECT_SM_LIST_SUPPRESS);
139         CASE_CODE(DETECT_SM_LIST_THRESHOLD);
140         CASE_CODE(DETECT_SM_LIST_MAX);
141     }
142     return "unknown";
143 }
144 
145 /** \param arg NULL or empty string */
DetectEngineContentModifierBufferSetup(DetectEngineCtx * de_ctx,Signature * s,const char * arg,int sm_type,int sm_list,AppProto alproto)146 int DetectEngineContentModifierBufferSetup(DetectEngineCtx *de_ctx,
147         Signature *s, const char *arg, int sm_type, int sm_list,
148         AppProto alproto)
149 {
150     SigMatch *sm = NULL;
151     int ret = -1;
152 
153     if (arg != NULL && strcmp(arg, "") != 0) {
154         SCLogError(SC_ERR_INVALID_ARGUMENT, "%s shouldn't be supplied "
155                    "with an argument", sigmatch_table[sm_type].name);
156         goto end;
157     }
158 
159     if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
160         SCLogError(SC_ERR_INVALID_SIGNATURE, "\"%s\" keyword seen "
161                    "with a sticky buffer still set.  Reset sticky buffer "
162                    "with pkt_data before using the modifier.",
163                    sigmatch_table[sm_type].name);
164         goto end;
165     }
166     if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, alproto)) {
167         SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting "
168                    "alprotos set");
169         goto end;
170     }
171 
172     sm = DetectGetLastSMByListId(s,
173             DETECT_SM_LIST_PMATCH, DETECT_CONTENT, -1);
174     if (sm == NULL) {
175         SCLogError(SC_ERR_INVALID_SIGNATURE, "\"%s\" keyword "
176                    "found inside the rule without a content context.  "
177                    "Please use a \"content\" keyword before using the "
178                    "\"%s\" keyword", sigmatch_table[sm_type].name,
179                    sigmatch_table[sm_type].name);
180         goto end;
181     }
182     DetectContentData *cd = (DetectContentData *)sm->ctx;
183     if (cd->flags & DETECT_CONTENT_RAWBYTES) {
184         SCLogError(SC_ERR_INVALID_SIGNATURE, "%s rule can not "
185                    "be used with the rawbytes rule keyword",
186                    sigmatch_table[sm_type].name);
187         goto end;
188     }
189     if (cd->flags & DETECT_CONTENT_REPLACE) {
190         SCLogError(SC_ERR_INVALID_SIGNATURE, "%s rule can not "
191                    "be used with the replace rule keyword",
192                    sigmatch_table[sm_type].name);
193         goto end;
194     }
195     if (cd->flags & (DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) {
196         SigMatch *pm = DetectGetLastSMByListPtr(s, sm->prev,
197             DETECT_CONTENT, DETECT_PCRE, -1);
198         if (pm != NULL) {
199             if (pm->type == DETECT_CONTENT) {
200                 DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
201                 tmp_cd->flags &= ~DETECT_CONTENT_RELATIVE_NEXT;
202             } else {
203                 DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
204                 tmp_pd->flags &= ~DETECT_PCRE_RELATIVE_NEXT;
205             }
206         }
207 
208         pm = DetectGetLastSMByListId(s, sm_list,
209             DETECT_CONTENT, DETECT_PCRE, -1);
210         if (pm != NULL) {
211             if (pm->type == DETECT_CONTENT) {
212                 DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
213                 tmp_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
214             } else {
215                 DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
216                 tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
217             }
218         }
219     }
220     s->alproto = alproto;
221     s->flags |= SIG_FLAG_APPLAYER;
222 
223     /* transfer the sm from the pmatch list to sm_list */
224     SigMatchTransferSigMatchAcrossLists(sm,
225                                         &s->init_data->smlists[DETECT_SM_LIST_PMATCH],
226                                         &s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH],
227                                         &s->init_data->smlists[sm_list],
228                                         &s->init_data->smlists_tail[sm_list]);
229 
230     ret = 0;
231  end:
232     return ret;
233 }
234 
SigMatchAlloc(void)235 SigMatch *SigMatchAlloc(void)
236 {
237     SigMatch *sm = SCMalloc(sizeof(SigMatch));
238     if (unlikely(sm == NULL))
239         return NULL;
240 
241     memset(sm, 0, sizeof(SigMatch));
242     sm->prev = NULL;
243     sm->next = NULL;
244     return sm;
245 }
246 
247 /** \brief free a SigMatch
248  *  \param sm SigMatch to free.
249  */
SigMatchFree(DetectEngineCtx * de_ctx,SigMatch * sm)250 void SigMatchFree(DetectEngineCtx *de_ctx, SigMatch *sm)
251 {
252     if (sm == NULL)
253         return;
254 
255     /** free the ctx, for that we call the Free func */
256     if (sm->ctx != NULL) {
257         if (sigmatch_table[sm->type].Free != NULL) {
258             sigmatch_table[sm->type].Free(de_ctx, sm->ctx);
259         }
260     }
261     SCFree(sm);
262 }
263 
SigTableGetIndex(const SigTableElmt * e)264 static enum DetectKeywordId SigTableGetIndex(const SigTableElmt *e)
265 {
266     const SigTableElmt *table = &sigmatch_table[0];
267     ptrdiff_t offset = e - table;
268     BUG_ON(offset >= DETECT_TBLSIZE);
269     return (enum DetectKeywordId)offset;
270 }
271 
272 /* Get the detection module by name */
SigTableGet(char * name)273 static SigTableElmt *SigTableGet(char *name)
274 {
275     SigTableElmt *st = NULL;
276     int i = 0;
277 
278     for (i = 0; i < DETECT_TBLSIZE; i++) {
279         st = &sigmatch_table[i];
280 
281         if (st->name != NULL) {
282             if (strcasecmp(name,st->name) == 0)
283                 return st;
284             if (st->alias != NULL && strcasecmp(name,st->alias) == 0)
285                 return st;
286         }
287     }
288 
289     return NULL;
290 }
291 
SigMatchSilentErrorEnabled(const DetectEngineCtx * de_ctx,const enum DetectKeywordId id)292 bool SigMatchSilentErrorEnabled(const DetectEngineCtx *de_ctx,
293         const enum DetectKeywordId id)
294 {
295     return de_ctx->sm_types_silent_error[id];
296 }
297 
SigMatchStrictEnabled(const enum DetectKeywordId id)298 bool SigMatchStrictEnabled(const enum DetectKeywordId id)
299 {
300     if (id < DETECT_TBLSIZE) {
301         return ((sigmatch_table[id].flags & SIGMATCH_STRICT_PARSING) != 0);
302     }
303     return false;
304 }
305 
SigTableApplyStrictCommandlineOption(const char * str)306 void SigTableApplyStrictCommandlineOption(const char *str)
307 {
308     if (str == NULL) {
309         /* nothing to be done */
310         return;
311     }
312 
313     /* "all" just sets the flag for each keyword */
314     if (strcmp(str, "all") == 0) {
315         for (int i = 0; i < DETECT_TBLSIZE; i++) {
316             SigTableElmt *st = &sigmatch_table[i];
317             st->flags |= SIGMATCH_STRICT_PARSING;
318         }
319         return;
320     }
321 
322     char *copy = SCStrdup(str);
323     if (copy == NULL)
324         FatalError(SC_ERR_MEM_ALLOC, "could not duplicate opt string");
325 
326     char *xsaveptr = NULL;
327     char *key = strtok_r(copy, ",", &xsaveptr);
328     while (key != NULL) {
329         SigTableElmt *st = SigTableGet(key);
330         if (st != NULL) {
331             st->flags |= SIGMATCH_STRICT_PARSING;
332         } else {
333             SCLogWarning(SC_ERR_CMD_LINE, "'strict' command line "
334                     "argument '%s' not found", key);
335         }
336         key = strtok_r(NULL, ",", &xsaveptr);
337     }
338 
339     SCFree(copy);
340 }
341 
342 /**
343  * \brief Append a SigMatch to the list type.
344  *
345  * \param s    Signature.
346  * \param new  The sig match to append.
347  * \param list The list to append to.
348  */
SigMatchAppendSMToList(Signature * s,SigMatch * new,int list)349 void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
350 {
351     if (list > 0 && (uint32_t)list >= s->init_data->smlists_array_size)
352     {
353         uint32_t old_size = s->init_data->smlists_array_size;
354         uint32_t new_size = (uint32_t)list + 1;
355         void *ptr = SCRealloc(s->init_data->smlists, (new_size * sizeof(SigMatch *)));
356         if (ptr == NULL)
357             abort();
358         s->init_data->smlists = ptr;
359         ptr = SCRealloc(s->init_data->smlists_tail, (new_size * sizeof(SigMatch *)));
360         if (ptr == NULL)
361             abort();
362         s->init_data->smlists_tail = ptr;
363         for (uint32_t i = old_size; i < new_size; i++) {
364             s->init_data->smlists[i] = NULL;
365             s->init_data->smlists_tail[i] = NULL;
366         }
367         s->init_data->smlists_array_size = new_size;
368     }
369 
370     if (s->init_data->smlists[list] == NULL) {
371         s->init_data->smlists[list] = new;
372         s->init_data->smlists_tail[list] = new;
373         new->next = NULL;
374         new->prev = NULL;
375     } else {
376         SigMatch *cur = s->init_data->smlists_tail[list];
377         cur->next = new;
378         new->prev = cur;
379         new->next = NULL;
380         s->init_data->smlists_tail[list] = new;
381     }
382 
383     new->idx = s->init_data->sm_cnt;
384     s->init_data->sm_cnt++;
385 }
386 
SigMatchRemoveSMFromList(Signature * s,SigMatch * sm,int sm_list)387 void SigMatchRemoveSMFromList(Signature *s, SigMatch *sm, int sm_list)
388 {
389     if (sm == s->init_data->smlists[sm_list]) {
390         s->init_data->smlists[sm_list] = sm->next;
391     }
392     if (sm == s->init_data->smlists_tail[sm_list]) {
393         s->init_data->smlists_tail[sm_list] = sm->prev;
394     }
395     if (sm->prev != NULL)
396         sm->prev->next = sm->next;
397     if (sm->next != NULL)
398         sm->next->prev = sm->prev;
399 
400     return;
401 }
402 
403 /**
404  * \brief Returns a pointer to the last SigMatch instance of a particular type
405  *        in a Signature of the payload list.
406  *
407  * \param s    Pointer to the tail of the sigmatch list
408  * \param type SigMatch type which has to be searched for in the Signature.
409  *
410  * \retval match Pointer to the last SigMatch instance of type 'type'.
411  */
SigMatchGetLastSMByType(SigMatch * sm,int type)412 static SigMatch *SigMatchGetLastSMByType(SigMatch *sm, int type)
413 {
414     while (sm != NULL) {
415         if (sm->type == type) {
416             return sm;
417         }
418         sm = sm->prev;
419     }
420 
421     return NULL;
422 }
423 
424 /** \brief get the last SigMatch from lists that support
425  *         MPM.
426  *  \note only supports the lists that are registered through
427  *        DetectBufferTypeSupportsMpm().
428  */
DetectGetLastSMFromMpmLists(const DetectEngineCtx * de_ctx,const Signature * s)429 SigMatch *DetectGetLastSMFromMpmLists(const DetectEngineCtx *de_ctx, const Signature *s)
430 {
431     SigMatch *sm_last = NULL;
432     SigMatch *sm_new;
433     uint32_t sm_type;
434 
435     /* if we have a sticky buffer, use that */
436     if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
437         if (!(DetectBufferTypeSupportsMpmGetById(de_ctx, s->init_data->list))) {
438             return NULL;
439         }
440 
441         sm_last = DetectGetLastSMByListPtr(s,
442                 s->init_data->smlists_tail[s->init_data->list],
443                 DETECT_CONTENT, -1);
444         return sm_last;
445     }
446 
447     /* otherwise brute force it */
448     for (sm_type = 0; sm_type < s->init_data->smlists_array_size; sm_type++) {
449         if (!DetectBufferTypeSupportsMpmGetById(de_ctx, sm_type))
450             continue;
451         SigMatch *sm_list = s->init_data->smlists_tail[sm_type];
452         sm_new = SigMatchGetLastSMByType(sm_list, DETECT_CONTENT);
453         if (sm_new == NULL)
454             continue;
455         if (sm_last == NULL || sm_new->idx > sm_last->idx)
456             sm_last = sm_new;
457     }
458 
459     return sm_last;
460 }
461 
462 /**
463  * \brief Returns the sm with the largest index (added latest) from the lists
464  *        passed to us.
465  *
466  * \retval Pointer to Last sm.
467  */
DetectGetLastSMFromLists(const Signature * s,...)468 SigMatch *DetectGetLastSMFromLists(const Signature *s, ...)
469 {
470     SigMatch *sm_last = NULL;
471     SigMatch *sm_new;
472 
473     /* otherwise brute force it */
474     for (int buf_type = 0; buf_type < (int)s->init_data->smlists_array_size; buf_type++) {
475         if (s->init_data->smlists[buf_type] == NULL)
476             continue;
477         if (s->init_data->list != DETECT_SM_LIST_NOTSET &&
478             buf_type != s->init_data->list)
479             continue;
480 
481         int sm_type;
482         va_list ap;
483         va_start(ap, s);
484 
485         for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
486         {
487             sm_new = SigMatchGetLastSMByType(s->init_data->smlists_tail[buf_type], sm_type);
488             if (sm_new == NULL)
489                 continue;
490             if (sm_last == NULL || sm_new->idx > sm_last->idx)
491                 sm_last = sm_new;
492         }
493         va_end(ap);
494     }
495 
496     return sm_last;
497 }
498 
499 /**
500  * \brief Returns the sm with the largest index (added last) from the list
501  *        passed to us as a pointer.
502  *
503  * \param sm_list pointer to the SigMatch we should look before
504  * \param va_args list of keyword types terminated by -1
505  *
506  * \retval sm_last to last sm.
507  */
DetectGetLastSMByListPtr(const Signature * s,SigMatch * sm_list,...)508 SigMatch *DetectGetLastSMByListPtr(const Signature *s, SigMatch *sm_list, ...)
509 {
510     SigMatch *sm_last = NULL;
511     SigMatch *sm_new;
512     int sm_type;
513 
514     va_list ap;
515     va_start(ap, sm_list);
516 
517     for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
518     {
519         sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
520         if (sm_new == NULL)
521             continue;
522         if (sm_last == NULL || sm_new->idx > sm_last->idx)
523             sm_last = sm_new;
524     }
525 
526     va_end(ap);
527 
528     return sm_last;
529 }
530 
531 /**
532  * \brief Returns the sm with the largest index (added last) from the list
533  *        passed to us as an id.
534  *
535  * \param list_id id of the list to be searched
536  * \param va_args list of keyword types terminated by -1
537  *
538  * \retval sm_last to last sm.
539  */
DetectGetLastSMByListId(const Signature * s,int list_id,...)540 SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...)
541 {
542     SigMatch *sm_last = NULL;
543     SigMatch *sm_new;
544     int sm_type;
545 
546     if ((uint32_t)list_id >= s->init_data->smlists_array_size) {
547         return NULL;
548     }
549     SigMatch *sm_list = s->init_data->smlists_tail[list_id];
550     if (sm_list == NULL)
551         return NULL;
552 
553     va_list ap;
554     va_start(ap, list_id);
555 
556     for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
557     {
558         sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
559         if (sm_new == NULL)
560             continue;
561         if (sm_last == NULL || sm_new->idx > sm_last->idx)
562             sm_last = sm_new;
563     }
564 
565     va_end(ap);
566 
567     return sm_last;
568 }
569 
570 /**
571  * \brief Returns the sm with the largest index (added latest) from this sig
572  *
573  * \retval sm_last Pointer to last sm
574  */
DetectGetLastSM(const Signature * s)575 SigMatch *DetectGetLastSM(const Signature *s)
576 {
577     const int nlists = s->init_data->smlists_array_size;
578     SigMatch *sm_last = NULL;
579     SigMatch *sm_new;
580     int i;
581 
582     for (i = 0; i < nlists; i ++) {
583         sm_new = s->init_data->smlists_tail[i];
584         if (sm_new == NULL)
585             continue;
586         if (sm_last == NULL || sm_new->idx > sm_last->idx)
587             sm_last = sm_new;
588     }
589 
590     return sm_last;
591 }
592 
SigMatchTransferSigMatchAcrossLists(SigMatch * sm,SigMatch ** src_sm_list,SigMatch ** src_sm_list_tail,SigMatch ** dst_sm_list,SigMatch ** dst_sm_list_tail)593 static void SigMatchTransferSigMatchAcrossLists(SigMatch *sm,
594         SigMatch **src_sm_list, SigMatch **src_sm_list_tail,
595         SigMatch **dst_sm_list, SigMatch **dst_sm_list_tail)
596 {
597     /* we won't do any checks for args */
598 
599     if (sm->prev != NULL)
600         sm->prev->next = sm->next;
601     if (sm->next != NULL)
602         sm->next->prev = sm->prev;
603 
604     if (sm == *src_sm_list)
605         *src_sm_list = sm->next;
606     if (sm == *src_sm_list_tail)
607         *src_sm_list_tail = sm->prev;
608 
609     if (*dst_sm_list == NULL) {
610         *dst_sm_list = sm;
611         *dst_sm_list_tail = sm;
612         sm->next = NULL;
613         sm->prev = NULL;
614     } else {
615         SigMatch *cur = *dst_sm_list_tail;
616         cur->next = sm;
617         sm->prev = cur;
618         sm->next = NULL;
619         *dst_sm_list_tail = sm;
620     }
621 
622     return;
623 }
624 
SigMatchListSMBelongsTo(const Signature * s,const SigMatch * key_sm)625 int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
626 {
627     if (key_sm == NULL)
628         return -1;
629 
630     const int nlists = s->init_data->smlists_array_size;
631     for (int list = 0; list < nlists; list++) {
632         const SigMatch *sm = s->init_data->smlists[list];
633         while (sm != NULL) {
634             if (sm == key_sm)
635                 return list;
636             sm = sm->next;
637         }
638     }
639 
640     SCLogError(SC_ERR_INVALID_SIGNATURE, "Unable to find the sm in any of the "
641                "sm lists");
642     return -1;
643 }
644 
SigParseOptions(DetectEngineCtx * de_ctx,Signature * s,char * optstr,char * output,size_t output_size)645 static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output, size_t output_size)
646 {
647     SigTableElmt *st = NULL;
648     char *optname = NULL;
649     char *optvalue = NULL;
650 
651     /* Trim leading space. */
652     while (isblank(*optstr)) {
653         optstr++;
654     }
655 
656     /* Look for the end of this option, handling escaped semicolons. */
657     char *optend = optstr;
658     for (;;) {
659         optend = strchr(optend, ';');
660         if (optend == NULL) {
661             SCLogError(SC_ERR_INVALID_SIGNATURE, "no terminating \";\" found");
662             goto error;
663         }
664         else if (optend > optstr && *(optend -1 ) == '\\') {
665             optend++;
666         } else {
667             break;
668         }
669     }
670     *(optend++) = '\0';
671 
672     /* Find the start of the option value. */
673     char *optvalptr = strchr(optstr, ':');
674     if (optvalptr) {
675         *(optvalptr++) = '\0';
676 
677         /* Trim trailing space from name. */
678         for (size_t i = strlen(optvalptr); i > 0; i--) {
679             if (isblank(optvalptr[i - 1])) {
680                 optvalptr[i - 1] = '\0';
681             } else {
682                 break;
683             }
684         }
685 
686         optvalue = optvalptr;
687     }
688 
689     /* Trim trailing space from name. */
690     for (size_t i = strlen(optstr); i > 0; i--) {
691         if (isblank(optstr[i - 1])) {
692             optstr[i - 1] = '\0';
693         } else {
694             break;
695         }
696     }
697     optname = optstr;
698 
699     /* Call option parsing */
700     st = SigTableGet(optname);
701     if (st == NULL || st->Setup == NULL) {
702         SCLogError(SC_ERR_RULE_KEYWORD_UNKNOWN, "unknown rule keyword '%s'.", optname);
703         goto error;
704     }
705 
706     if (!(st->flags & (SIGMATCH_NOOPT|SIGMATCH_OPTIONAL_OPT))) {
707         if (optvalue == NULL || strlen(optvalue) == 0) {
708             SCLogError(SC_ERR_INVALID_SIGNATURE,
709                     "invalid formatting or malformed option to %s keyword: '%s'", optname, optstr);
710             goto error;
711         }
712     } else if (st->flags & SIGMATCH_NOOPT) {
713         if (optvalue && strlen(optvalue)) {
714             SCLogError(SC_ERR_INVALID_SIGNATURE, "unexpected option to %s keyword: '%s'", optname,
715                     optstr);
716             goto error;
717         }
718     }
719     s->init_data->negated = false;
720 
721     if (st->flags & SIGMATCH_INFO_DEPRECATED) {
722 #define URL "https://suricata-ids.org/about/deprecation-policy/"
723         if (st->alternative == 0)
724             SCLogWarning(SC_WARN_DEPRECATED, "keyword '%s' is deprecated "
725                     "and will be removed soon. See %s", st->name, URL);
726         else
727             SCLogWarning(SC_WARN_DEPRECATED, "keyword '%s' is deprecated "
728                     "and will be removed soon. Use '%s' instead. "
729                     "See %s", st->name, sigmatch_table[st->alternative].name, URL);
730 #undef URL
731     }
732 
733     int setup_ret = 0;
734 
735     /* Validate double quoting, trimming trailing white space along the way. */
736     if (optvalue != NULL && strlen(optvalue) > 0) {
737         size_t ovlen = strlen(optvalue);
738         char *ptr = optvalue;
739 
740         /* skip leading whitespace */
741         while (ovlen > 0) {
742             if (!isblank(*ptr))
743                 break;
744             ptr++;
745             ovlen--;
746         }
747         if (ovlen == 0) {
748             SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
749                     optname, optstr);
750             goto error;
751         }
752 
753         /* see if value is negated */
754         if ((st->flags & SIGMATCH_HANDLE_NEGATION) && *ptr == '!') {
755             s->init_data->negated = true;
756             ptr++;
757             ovlen--;
758         }
759         /* skip more whitespace */
760         while (ovlen > 0) {
761             if (!isblank(*ptr))
762                 break;
763             ptr++;
764             ovlen--;
765         }
766         if (ovlen == 0) {
767             SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting or malformed option to %s keyword: \'%s\'",
768                     optname, optstr);
769             goto error;
770         }
771         /* if quoting is mandatory, enforce it */
772         if (st->flags & SIGMATCH_QUOTES_MANDATORY && ovlen && *ptr != '"') {
773             SCLogError(SC_ERR_INVALID_SIGNATURE, "invalid formatting to %s keyword: "
774                     "value must be double quoted \'%s\'", optname, optstr);
775             goto error;
776         }
777 
778         if ((st->flags & (SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_QUOTES_MANDATORY))
779                 && ovlen && *ptr == '"')
780         {
781             for (; ovlen > 0; ovlen--) {
782                 if (isblank(ptr[ovlen - 1])) {
783                     ptr[ovlen - 1] = '\0';
784                 } else {
785                     break;
786                 }
787             }
788             if (ovlen && ptr[ovlen - 1] != '"') {
789                 SCLogError(SC_ERR_INVALID_SIGNATURE,
790                     "bad option value formatting (possible missing semicolon) "
791                     "for keyword %s: \'%s\'", optname, optvalue);
792                 goto error;
793             }
794             if (ovlen > 1) {
795                 /* strip leading " */
796                 ptr++;
797                 ovlen--;
798                 ptr[ovlen - 1] = '\0';
799                 ovlen--;
800             }
801             if (ovlen == 0) {
802                 SCLogError(SC_ERR_INVALID_SIGNATURE,
803                     "bad input "
804                     "for keyword %s: \'%s\'", optname, optvalue);
805                 goto error;
806             }
807         } else {
808             if (*ptr == '"') {
809                 SCLogError(SC_ERR_INVALID_SIGNATURE, "quotes on %s keyword that doesn't support them: \'%s\'",
810                         optname, optstr);
811                 goto error;
812             }
813         }
814         /* setup may or may not add a new SigMatch to the list */
815         setup_ret = st->Setup(de_ctx, s, ptr);
816     } else {
817         /* setup may or may not add a new SigMatch to the list */
818         setup_ret = st->Setup(de_ctx, s, NULL);
819     }
820     if (setup_ret < 0) {
821         SCLogDebug("\"%s\" failed to setup", st->name);
822 
823         /* handle 'silent' error case */
824         if (setup_ret == -2) {
825             enum DetectKeywordId idx = SigTableGetIndex(st);
826             if (de_ctx->sm_types_silent_error[idx] == false) {
827                 de_ctx->sm_types_silent_error[idx] = true;
828                 return -1;
829             }
830             return -2;
831         }
832         return setup_ret;
833     }
834     s->init_data->negated = false;
835 
836     if (strlen(optend) > 0) {
837         strlcpy(output, optend, output_size);
838         return 1;
839     }
840 
841     return 0;
842 
843 error:
844     return -1;
845 }
846 
847 /** \brief Parse address string and update signature
848  *
849  *  \retval 0 ok, -1 error
850  */
SigParseAddress(DetectEngineCtx * de_ctx,Signature * s,const char * addrstr,char flag)851 static int SigParseAddress(DetectEngineCtx *de_ctx,
852         Signature *s, const char *addrstr, char flag)
853 {
854     SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
855 
856     /* pass on to the address(list) parser */
857     if (flag == 0) {
858         if (strcasecmp(addrstr, "any") == 0)
859             s->flags |= SIG_FLAG_SRC_ANY;
860 
861         s->init_data->src = DetectParseAddress(de_ctx, addrstr,
862                 &s->init_data->src_contains_negation);
863         if (s->init_data->src == NULL)
864             goto error;
865     } else {
866         if (strcasecmp(addrstr, "any") == 0)
867             s->flags |= SIG_FLAG_DST_ANY;
868 
869         s->init_data->dst = DetectParseAddress(de_ctx, addrstr,
870                 &s->init_data->dst_contains_negation);
871         if (s->init_data->dst == NULL)
872             goto error;
873     }
874 
875     return 0;
876 
877 error:
878     return -1;
879 }
880 
881 /**
882  * \brief Parses the protocol supplied by the Signature.
883  *
884  *        http://www.iana.org/assignments/protocol-numbers
885  *
886  * \param s        Pointer to the Signature instance to which the parsed
887  *                 protocol has to be added.
888  * \param protostr Pointer to the character string containing the protocol name.
889  *
890  * \retval  0 On successfully parsing the protocl sent as the argument.
891  * \retval -1 On failure
892  */
SigParseProto(Signature * s,const char * protostr)893 static int SigParseProto(Signature *s, const char *protostr)
894 {
895     SCEnter();
896 
897     int r = DetectProtoParse(&s->proto, (char *)protostr);
898     if (r < 0) {
899         s->alproto = AppLayerGetProtoByName((char *)protostr);
900         /* indicate that the signature is app-layer */
901         if (s->alproto != ALPROTO_UNKNOWN) {
902             s->flags |= SIG_FLAG_APPLAYER;
903 
904             AppLayerProtoDetectSupportedIpprotos(s->alproto, s->proto.proto);
905         }
906         else {
907             SCLogError(SC_ERR_UNKNOWN_PROTOCOL, "protocol \"%s\" cannot be used "
908                        "in a signature.  Either detection for this protocol "
909                        "is not yet supported OR detection has been disabled for "
910                        "protocol through the yaml option "
911                        "app-layer.protocols.%s.detection-enabled", protostr,
912                        protostr);
913             SCReturnInt(-1);
914         }
915     }
916 
917     /* if any of these flags are set they are set in a mutually exclusive
918      * manner */
919     if (s->proto.flags & DETECT_PROTO_ONLY_PKT) {
920         s->flags |= SIG_FLAG_REQUIRE_PACKET;
921     } else if (s->proto.flags & DETECT_PROTO_ONLY_STREAM) {
922         s->flags |= SIG_FLAG_REQUIRE_STREAM;
923     }
924 
925     SCReturnInt(0);
926 }
927 
928 /**
929  * \brief Parses the port(source or destination) field, from a Signature.
930  *
931  * \param s       Pointer to the signature which has to be updated with the
932  *                port information.
933  * \param portstr Pointer to the character string containing the port info.
934  * \param         Flag which indicates if the portstr received is src or dst
935  *                port.  For src port: flag = 0, dst port: flag = 1.
936  *
937  * \retval  0 On success.
938  * \retval -1 On failure.
939  */
SigParsePort(const DetectEngineCtx * de_ctx,Signature * s,const char * portstr,char flag)940 static int SigParsePort(const DetectEngineCtx *de_ctx,
941         Signature *s, const char *portstr, char flag)
942 {
943     int r = 0;
944 
945     /* XXX VJ exclude handling this for none UDP/TCP proto's */
946 
947     SCLogDebug("Port group \"%s\" to be parsed", portstr);
948 
949     if (flag == 0) {
950         if (strcasecmp(portstr, "any") == 0)
951             s->flags |= SIG_FLAG_SP_ANY;
952 
953         r = DetectPortParse(de_ctx, &s->sp, (char *)portstr);
954     } else if (flag == 1) {
955         if (strcasecmp(portstr, "any") == 0)
956             s->flags |= SIG_FLAG_DP_ANY;
957 
958         r = DetectPortParse(de_ctx, &s->dp, (char *)portstr);
959     }
960 
961     if (r < 0)
962         return -1;
963 
964     return 0;
965 }
966 
967 /** \retval 1 valid
968  *  \retval 0 invalid
969  */
SigParseActionRejectValidate(const char * action)970 static int SigParseActionRejectValidate(const char *action)
971 {
972 #ifdef HAVE_LIBNET11
973 #if defined HAVE_LIBCAP_NG && !defined HAVE_LIBNET_CAPABILITIES
974     if (sc_set_caps == TRUE) {
975         SCLogError(SC_ERR_LIBNET11_INCOMPATIBLE_WITH_LIBCAP_NG, "Libnet 1.1 is "
976             "incompatible with POSIX based capabilities with privs dropping. "
977             "For rejects to work, run as root/super user.");
978         return 0;
979     }
980 #endif
981 #else /* no libnet 1.1 */
982     SCLogError(SC_ERR_LIBNET_REQUIRED_FOR_ACTION, "Libnet 1.1.x is "
983             "required for action \"%s\" but is not compiled into Suricata",
984             action);
985     return 0;
986 #endif
987     return 1;
988 }
989 
990 /**
991  * \brief Parses the action that has been used by the Signature and allots it
992  *        to its Signature instance.
993  *
994  * \param s      Pointer to the Signature instance to which the action belongs.
995  * \param action Pointer to the action string used by the Signature.
996  *
997  * \retval  0 On successfully parsing the action string and adding it to the
998  *            Signature.
999  * \retval -1 On failure.
1000  */
SigParseAction(Signature * s,const char * action)1001 static int SigParseAction(Signature *s, const char *action)
1002 {
1003     if (strcasecmp(action, "alert") == 0) {
1004         s->action = ACTION_ALERT;
1005     } else if (strcasecmp(action, "drop") == 0) {
1006         s->action = ACTION_DROP;
1007     } else if (strcasecmp(action, "pass") == 0) {
1008         s->action = ACTION_PASS;
1009     } else if (strcasecmp(action, "reject") == 0 ||
1010                strcasecmp(action, "rejectsrc") == 0)
1011     {
1012         if (!(SigParseActionRejectValidate(action)))
1013             return -1;
1014         s->action = ACTION_REJECT|ACTION_DROP;
1015     } else if (strcasecmp(action, "rejectdst") == 0) {
1016         if (!(SigParseActionRejectValidate(action)))
1017             return -1;
1018         s->action = ACTION_REJECT_DST|ACTION_DROP;
1019     } else if (strcasecmp(action, "rejectboth") == 0) {
1020         if (!(SigParseActionRejectValidate(action)))
1021             return -1;
1022         s->action = ACTION_REJECT_BOTH|ACTION_DROP;
1023     } else if (strcasecmp(action, "config") == 0) {
1024         s->action = ACTION_CONFIG;
1025         s->flags |= SIG_FLAG_NOALERT;
1026     } else {
1027         SCLogError(SC_ERR_INVALID_ACTION,"An invalid action \"%s\" was given",action);
1028         return -1;
1029     }
1030     return 0;
1031 }
1032 
1033 /**
1034  * \brief Parse the next token in rule.
1035  *
1036  * For rule parsing a token is considered to be a string of characters
1037  * separated by white space.
1038  *
1039  * \param input double pointer to input buffer, will be advanced as input is
1040  *     parsed.
1041  * \param output buffer to copy token into.
1042  * \param output_size length of output buffer.
1043  */
SigParseToken(char ** input,char * output,const size_t output_size)1044 static inline int SigParseToken(char **input, char *output,
1045     const size_t output_size)
1046 {
1047     size_t len = *input == NULL ? 0 : strlen(*input);
1048 
1049     if (!len) {
1050         return 0;
1051     }
1052 
1053     while (len && isblank(**input)) {
1054         (*input)++;
1055         len--;
1056     }
1057 
1058     char *endptr = strpbrk(*input, " \t\n\r");
1059     if (endptr != NULL) {
1060         *(endptr++) = '\0';
1061     }
1062     strlcpy(output, *input, output_size);
1063     *input = endptr;
1064 
1065     return 1;
1066 }
1067 
1068 /**
1069  * \brief Parse the next rule "list" token.
1070  *
1071  * Parses rule tokens that may be lists such as addresses and ports
1072  * handling the case when they may not be lists.
1073  *
1074  * \param input double pointer to input buffer, will be advanced as input is
1075  *     parsed.
1076  * \param output buffer to copy token into.
1077  * \param output_size length of output buffer.
1078  */
SigParseList(char ** input,char * output,const size_t output_size)1079 static inline int SigParseList(char **input, char *output,
1080     const size_t output_size)
1081 {
1082     int in_list = 0;
1083     size_t len = *input != NULL ? strlen(*input) : 0;
1084 
1085     if (len == 0) {
1086         return 0;
1087     }
1088 
1089     while (len && isblank(**input)) {
1090         (*input)++;
1091         len--;
1092     }
1093 
1094     size_t i = 0;
1095     for (i = 0; i < len; i++) {
1096         char c = (*input)[i];
1097         if (c == '[') {
1098             in_list++;
1099         } else if (c == ']') {
1100             in_list--;
1101         } else if (c == ' ') {
1102             if (!in_list) {
1103                 break;
1104             }
1105         }
1106     }
1107     if (i == len) {
1108         *input = NULL;
1109         return 0;
1110     }
1111     (*input)[i] = '\0';
1112     strlcpy(output, *input, output_size);
1113     *input = *input + i + 1;
1114 
1115     return 1;
1116 }
1117 
1118 /**
1119  *  \internal
1120  *  \brief split a signature string into a few blocks for further parsing
1121  */
SigParseBasics(DetectEngineCtx * de_ctx,Signature * s,const char * sigstr,SignatureParser * parser,uint8_t addrs_direction)1122 static int SigParseBasics(DetectEngineCtx *de_ctx,
1123         Signature *s, const char *sigstr, SignatureParser *parser, uint8_t addrs_direction)
1124 {
1125     char *index, dup[DETECT_MAX_RULE_SIZE];
1126 
1127     strlcpy(dup, sigstr, DETECT_MAX_RULE_SIZE);
1128     index = dup;
1129 
1130     /* Action. */
1131     SigParseToken(&index, parser->action, sizeof(parser->action));
1132 
1133     /* Protocol. */
1134     SigParseList(&index, parser->protocol, sizeof(parser->protocol));
1135 
1136     /* Source. */
1137     SigParseList(&index, parser->src, sizeof(parser->src));
1138 
1139     /* Source port(s). */
1140     SigParseList(&index, parser->sp, sizeof(parser->sp));
1141 
1142     /* Direction. */
1143     SigParseToken(&index, parser->direction, sizeof(parser->direction));
1144 
1145     /* Destination. */
1146     SigParseList(&index, parser->dst, sizeof(parser->dst));
1147 
1148     /* Destination port(s). */
1149     SigParseList(&index, parser->dp, sizeof(parser->dp));
1150 
1151     /* Options. */
1152     if (index == NULL) {
1153         SCLogError(SC_ERR_INVALID_RULE_ARGUMENT, "no rule options.");
1154         goto error;
1155     }
1156     while (isspace(*index) || *index == '(') {
1157         index++;
1158     }
1159     for (size_t i = strlen(index); i > 0; i--) {
1160         if (isspace(index[i - 1]) || index[i - 1] == ')') {
1161             index[i - 1] = '\0';
1162         } else {
1163             break;
1164         }
1165     }
1166     strlcpy(parser->opts, index, sizeof(parser->opts));
1167 
1168     /* Parse Action */
1169     if (SigParseAction(s, parser->action) < 0)
1170         goto error;
1171 
1172     if (SigParseProto(s, parser->protocol) < 0)
1173         goto error;
1174 
1175     if (strcmp(parser->direction, "<>") == 0) {
1176         s->init_data->init_flags |= SIG_FLAG_INIT_BIDIREC;
1177     } else if (strcmp(parser->direction, "->") != 0) {
1178         SCLogError(SC_ERR_INVALID_DIRECTION,
1179                 "\"%s\" is not a valid direction modifier, "
1180                 "\"->\" and \"<>\" are supported.", parser->direction);
1181         goto error;
1182     }
1183 
1184     /* Parse Address & Ports */
1185     if (SigParseAddress(de_ctx, s, parser->src, SIG_DIREC_SRC ^ addrs_direction) < 0)
1186        goto error;
1187 
1188     if (SigParseAddress(de_ctx, s, parser->dst, SIG_DIREC_DST ^ addrs_direction) < 0)
1189         goto error;
1190 
1191     /* By AWS - Traditionally we should be doing this only for tcp/udp/sctp,
1192      * but we do it for regardless of ip proto, since the dns/dnstcp/dnsudp
1193      * changes that we made sees to it that at this point of time we don't
1194      * set the ip proto for the sig.  We do it a bit later. */
1195     if (SigParsePort(de_ctx, s, parser->sp, SIG_DIREC_SRC ^ addrs_direction) < 0)
1196         goto error;
1197     if (SigParsePort(de_ctx, s, parser->dp, SIG_DIREC_DST ^ addrs_direction) < 0)
1198         goto error;
1199 
1200     return 0;
1201 
1202 error:
1203     return -1;
1204 }
1205 
1206 /**
1207  *  \brief parse a signature
1208  *
1209  *  \param de_ctx detection engine ctx to add it to
1210  *  \param s memory structure to store the signature in
1211  *  \param sigstr the raw signature as a null terminated string
1212  *  \param addrs_direction direction (for bi-directional sigs)
1213  *
1214  *  \param -1 parse error
1215  *  \param 0 ok
1216  */
SigParse(DetectEngineCtx * de_ctx,Signature * s,const char * sigstr,uint8_t addrs_direction,SignatureParser * parser)1217 static int SigParse(DetectEngineCtx *de_ctx, Signature *s,
1218         const char *sigstr, uint8_t addrs_direction, SignatureParser *parser)
1219 {
1220     SCEnter();
1221 
1222     if (!rs_check_utf8(sigstr)) {
1223         SCLogError(SC_ERR_RULE_INVALID_UTF8, "rule is not valid UTF-8");
1224         SCReturnInt(-1);
1225     }
1226 
1227     s->sig_str = SCStrdup(sigstr);
1228     if (unlikely(s->sig_str == NULL)) {
1229         SCReturnInt(-1);
1230     }
1231 
1232     int ret = SigParseBasics(de_ctx, s, sigstr, parser, addrs_direction);
1233     if (ret < 0) {
1234         SCLogDebug("SigParseBasics failed");
1235         SCReturnInt(-1);
1236     }
1237 
1238     /* we can have no options, so make sure we have them */
1239     if (strlen(parser->opts) > 0) {
1240         size_t buffer_size = strlen(parser->opts) + 1;
1241         char input[buffer_size];
1242         char output[buffer_size];
1243         memset(input, 0x00, buffer_size);
1244         memcpy(input, parser->opts, strlen(parser->opts)+1);
1245 
1246         /* loop the option parsing. Each run processes one option
1247          * and returns the rest of the option string through the
1248          * output variable. */
1249         do {
1250             memset(output, 0x00, buffer_size);
1251             ret = SigParseOptions(de_ctx, s, input, output, buffer_size);
1252             if (ret == 1) {
1253                 memcpy(input, output, buffer_size);
1254             }
1255 
1256         } while (ret == 1);
1257     }
1258 
1259     DetectIPProtoRemoveAllSMs(de_ctx, s);
1260 
1261     SCReturnInt(ret);
1262 }
1263 
SigAlloc(void)1264 Signature *SigAlloc (void)
1265 {
1266     Signature *sig = SCMalloc(sizeof(Signature));
1267     if (unlikely(sig == NULL))
1268         return NULL;
1269     memset(sig, 0, sizeof(Signature));
1270 
1271     sig->init_data = SCCalloc(1, sizeof(SignatureInitData));
1272     if (sig->init_data == NULL) {
1273         SCFree(sig);
1274         return NULL;
1275     }
1276 
1277     sig->init_data->smlists_array_size = DetectBufferTypeMaxId();
1278     SCLogDebug("smlists size %u", sig->init_data->smlists_array_size);
1279     sig->init_data->smlists = SCCalloc(sig->init_data->smlists_array_size, sizeof(SigMatch *));
1280     if (sig->init_data->smlists == NULL) {
1281         SCFree(sig->init_data);
1282         SCFree(sig);
1283         return NULL;
1284     }
1285 
1286     sig->init_data->smlists_tail = SCCalloc(sig->init_data->smlists_array_size, sizeof(SigMatch *));
1287     if (sig->init_data->smlists_tail == NULL) {
1288         SCFree(sig->init_data->smlists);
1289         SCFree(sig->init_data);
1290         SCFree(sig);
1291         return NULL;
1292     }
1293 
1294     /* assign it to -1, so that we can later check if the value has been
1295      * overwritten after the Signature has been parsed, and if it hasn't been
1296      * overwritten, we can then assign the default value of 3 */
1297     sig->prio = -1;
1298 
1299     sig->init_data->list = DETECT_SM_LIST_NOTSET;
1300     return sig;
1301 }
1302 
1303 /**
1304  * \internal
1305  * \brief Free Metadata list
1306  *
1307  * \param s Pointer to the signature
1308  */
SigMetadataFree(Signature * s)1309 static void SigMetadataFree(Signature *s)
1310 {
1311     SCEnter();
1312 
1313     DetectMetadata *mdata = NULL;
1314     DetectMetadata *next_mdata = NULL;
1315 
1316     if (s == NULL || s->metadata == NULL) {
1317         SCReturn;
1318     }
1319 
1320     SCLogDebug("s %p, s->metadata %p", s, s->metadata);
1321 
1322     for (mdata = s->metadata->list; mdata != NULL;)   {
1323         next_mdata = mdata->next;
1324         DetectMetadataFree(mdata);
1325         mdata = next_mdata;
1326     }
1327     SCFree(s->metadata->json_str);
1328     SCFree(s->metadata);
1329     s->metadata = NULL;
1330 
1331     SCReturn;
1332 }
1333 
1334 /**
1335  * \internal
1336  * \brief Free Reference list
1337  *
1338  * \param s Pointer to the signature
1339  */
SigRefFree(Signature * s)1340 static void SigRefFree (Signature *s)
1341 {
1342     SCEnter();
1343 
1344     DetectReference *ref = NULL;
1345     DetectReference *next_ref = NULL;
1346 
1347     if (s == NULL) {
1348         SCReturn;
1349     }
1350 
1351     SCLogDebug("s %p, s->references %p", s, s->references);
1352 
1353     for (ref = s->references; ref != NULL;)   {
1354         next_ref = ref->next;
1355         DetectReferenceFree(ref);
1356         ref = next_ref;
1357     }
1358 
1359     s->references = NULL;
1360 
1361     SCReturn;
1362 }
1363 
SigMatchFreeArrays(DetectEngineCtx * de_ctx,Signature * s,int ctxs)1364 static void SigMatchFreeArrays(DetectEngineCtx *de_ctx, Signature *s, int ctxs)
1365 {
1366     if (s != NULL) {
1367         int type;
1368         for (type = 0; type < DETECT_SM_LIST_MAX; type++) {
1369             if (s->sm_arrays[type] != NULL) {
1370                 if (ctxs) {
1371                     SigMatchData *smd = s->sm_arrays[type];
1372                     while(1) {
1373                         if (sigmatch_table[smd->type].Free != NULL) {
1374                             sigmatch_table[smd->type].Free(de_ctx, smd->ctx);
1375                         }
1376                         if (smd->is_last)
1377                             break;
1378                         smd++;
1379                     }
1380                 }
1381 
1382                 SCFree(s->sm_arrays[type]);
1383             }
1384         }
1385     }
1386 }
1387 
SigFree(DetectEngineCtx * de_ctx,Signature * s)1388 void SigFree(DetectEngineCtx *de_ctx, Signature *s)
1389 {
1390     if (s == NULL)
1391         return;
1392 
1393     if (s->CidrDst != NULL)
1394         IPOnlyCIDRListFree(s->CidrDst);
1395 
1396     if (s->CidrSrc != NULL)
1397         IPOnlyCIDRListFree(s->CidrSrc);
1398 
1399     int i;
1400 
1401     if (s->init_data && s->init_data->transforms.cnt) {
1402         for(i = 0; i < s->init_data->transforms.cnt; i++) {
1403             if (s->init_data->transforms.transforms[i].options) {
1404                 SCFree(s->init_data->transforms.transforms[i].options);
1405                 s->init_data->transforms.transforms[i].options = NULL;
1406             }
1407         }
1408     }
1409     if (s->init_data) {
1410         const int nlists = s->init_data->smlists_array_size;
1411         for (i = 0; i < nlists; i++) {
1412             SigMatch *sm = s->init_data->smlists[i];
1413             while (sm != NULL) {
1414                 SigMatch *nsm = sm->next;
1415                 SigMatchFree(de_ctx, sm);
1416                 sm = nsm;
1417             }
1418         }
1419     }
1420     SigMatchFreeArrays(de_ctx, s, (s->init_data == NULL));
1421     if (s->init_data) {
1422         SCFree(s->init_data->smlists);
1423         SCFree(s->init_data->smlists_tail);
1424         SCFree(s->init_data);
1425         s->init_data = NULL;
1426     }
1427 
1428     if (s->sp != NULL) {
1429         DetectPortCleanupList(NULL, s->sp);
1430     }
1431     if (s->dp != NULL) {
1432         DetectPortCleanupList(NULL, s->dp);
1433     }
1434 
1435     if (s->msg != NULL)
1436         SCFree(s->msg);
1437 
1438     if (s->addr_src_match4 != NULL) {
1439         SCFree(s->addr_src_match4);
1440     }
1441     if (s->addr_dst_match4 != NULL) {
1442         SCFree(s->addr_dst_match4);
1443     }
1444     if (s->addr_src_match6 != NULL) {
1445         SCFree(s->addr_src_match6);
1446     }
1447     if (s->addr_dst_match6 != NULL) {
1448         SCFree(s->addr_dst_match6);
1449     }
1450     if (s->sig_str != NULL) {
1451         SCFree(s->sig_str);
1452     }
1453 
1454     SigRefFree(s);
1455     SigMetadataFree(s);
1456 
1457     DetectEngineAppInspectionEngineSignatureFree(de_ctx, s);
1458 
1459     SCFree(s);
1460 }
1461 
DetectSignatureAddTransform(Signature * s,int transform,void * options)1462 int DetectSignatureAddTransform(Signature *s, int transform, void *options)
1463 {
1464     /* we only support buffers */
1465     if (s->init_data->list == 0) {
1466         SCReturnInt(-1);
1467     }
1468     if (!s->init_data->list_set) {
1469         SCLogError(SC_ERR_INVALID_SIGNATURE, "transforms must directly follow stickybuffers");
1470         SCReturnInt(-1);
1471     }
1472     if (s->init_data->transforms.cnt >= DETECT_TRANSFORMS_MAX) {
1473         SCReturnInt(-1);
1474     }
1475 
1476     s->init_data->transforms.transforms[s->init_data->transforms.cnt].transform = transform;
1477     s->init_data->transforms.transforms[s->init_data->transforms.cnt].options = options;
1478 
1479     s->init_data->transforms.cnt++;
1480     SCLogDebug("Added transform #%d [%s]",
1481             s->init_data->transforms.cnt,
1482             s->sig_str);
1483 
1484     SCReturnInt(0);
1485 }
1486 
DetectSignatureSetAppProto(Signature * s,AppProto alproto)1487 int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
1488 {
1489     if (alproto == ALPROTO_UNKNOWN ||
1490         alproto >= ALPROTO_FAILED) {
1491         SCLogError(SC_ERR_INVALID_ARGUMENT, "invalid alproto %u", alproto);
1492         return -1;
1493     }
1494 
1495     if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(alproto, s->alproto)) {
1496         SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS,
1497             "can't set rule app proto to %s: already set to %s",
1498             AppProtoToString(alproto), AppProtoToString(s->alproto));
1499         return -1;
1500     }
1501 
1502     // allow to keep HTTP2 as s->alproto with HTTP1 alproto keywords
1503     if (!AppProtoEquals(alproto, s->alproto)) {
1504         s->alproto = alproto;
1505     }
1506     s->flags |= SIG_FLAG_APPLAYER;
1507     return 0;
1508 }
1509 
1510 /**
1511  *  \internal
1512  *  \brief build address match array for cache efficient matching
1513  *
1514  *  \param s the signature
1515  */
SigBuildAddressMatchArray(Signature * s)1516 static void SigBuildAddressMatchArray(Signature *s)
1517 {
1518     /* source addresses */
1519     uint16_t cnt = 0;
1520     uint16_t idx = 0;
1521     DetectAddress *da = s->init_data->src->ipv4_head;
1522     for ( ; da != NULL; da = da->next) {
1523         cnt++;
1524     }
1525     if (cnt > 0) {
1526         s->addr_src_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1527         if (s->addr_src_match4 == NULL) {
1528             exit(EXIT_FAILURE);
1529         }
1530 
1531         for (da = s->init_data->src->ipv4_head; da != NULL; da = da->next) {
1532             s->addr_src_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1533             s->addr_src_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1534             idx++;
1535         }
1536         s->addr_src_match4_cnt = cnt;
1537     }
1538 
1539     /* destination addresses */
1540     cnt = 0;
1541     idx = 0;
1542     da = s->init_data->dst->ipv4_head;
1543     for ( ; da != NULL; da = da->next) {
1544         cnt++;
1545     }
1546     if (cnt > 0) {
1547         s->addr_dst_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1548         if (s->addr_dst_match4 == NULL) {
1549             exit(EXIT_FAILURE);
1550         }
1551 
1552         for (da = s->init_data->dst->ipv4_head; da != NULL; da = da->next) {
1553             s->addr_dst_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1554             s->addr_dst_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1555             idx++;
1556         }
1557         s->addr_dst_match4_cnt = cnt;
1558     }
1559 
1560     /* source addresses IPv6 */
1561     cnt = 0;
1562     idx = 0;
1563     da = s->init_data->src->ipv6_head;
1564     for ( ; da != NULL; da = da->next) {
1565         cnt++;
1566     }
1567     if (cnt > 0) {
1568         s->addr_src_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1569         if (s->addr_src_match6 == NULL) {
1570             exit(EXIT_FAILURE);
1571         }
1572 
1573         for (da = s->init_data->src->ipv6_head; da != NULL; da = da->next) {
1574             s->addr_src_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1575             s->addr_src_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1576             s->addr_src_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1577             s->addr_src_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1578             s->addr_src_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1579             s->addr_src_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1580             s->addr_src_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1581             s->addr_src_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1582             idx++;
1583         }
1584         s->addr_src_match6_cnt = cnt;
1585     }
1586 
1587     /* destination addresses IPv6 */
1588     cnt = 0;
1589     idx = 0;
1590     da = s->init_data->dst->ipv6_head;
1591     for ( ; da != NULL; da = da->next) {
1592         cnt++;
1593     }
1594     if (cnt > 0) {
1595         s->addr_dst_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1596         if (s->addr_dst_match6 == NULL) {
1597             exit(EXIT_FAILURE);
1598         }
1599 
1600         for (da = s->init_data->dst->ipv6_head; da != NULL; da = da->next) {
1601             s->addr_dst_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1602             s->addr_dst_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1603             s->addr_dst_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1604             s->addr_dst_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1605             s->addr_dst_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1606             s->addr_dst_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1607             s->addr_dst_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1608             s->addr_dst_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1609             idx++;
1610         }
1611         s->addr_dst_match6_cnt = cnt;
1612     }
1613 }
1614 
SigMatchListLen(SigMatch * sm)1615 static int SigMatchListLen(SigMatch *sm)
1616 {
1617     int len = 0;
1618     for (; sm != NULL; sm = sm->next)
1619         len++;
1620 
1621     return len;
1622 }
1623 
1624 /** \brief convert SigMatch list to SigMatchData array
1625  *  \note ownership of sm->ctx is transferred to smd->ctx
1626  */
SigMatchList2DataArray(SigMatch * head)1627 SigMatchData* SigMatchList2DataArray(SigMatch *head)
1628 {
1629     int len = SigMatchListLen(head);
1630     if (len == 0)
1631         return NULL;
1632 
1633     SigMatchData *smd = (SigMatchData *)SCCalloc(len, sizeof(SigMatchData));
1634     if (smd == NULL) {
1635         FatalError(SC_ERR_FATAL, "initializing the detection engine failed");
1636     }
1637     SigMatchData *out = smd;
1638 
1639     /* Copy sm type and Context into array */
1640     SigMatch *sm = head;
1641     for (; sm != NULL; sm = sm->next, smd++) {
1642         smd->type = sm->type;
1643         smd->ctx = sm->ctx;
1644         sm->ctx = NULL; // SigMatch no longer owns the ctx
1645         smd->is_last = (sm->next == NULL);
1646     }
1647     return out;
1648 }
1649 
1650 /**
1651  *  \internal
1652  *  \brief validate a just parsed signature for internal inconsistencies
1653  *
1654  *  \param s just parsed signature
1655  *
1656  *  \retval 0 invalid
1657  *  \retval 1 valid
1658  */
SigValidate(DetectEngineCtx * de_ctx,Signature * s)1659 static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
1660 {
1661     uint32_t sig_flags = 0;
1662     SigMatch *sm;
1663     const int nlists = s->init_data->smlists_array_size;
1664 
1665     SCEnter();
1666 
1667     /* check for sticky buffers that were set w/o matches
1668      * e.g. alert ... (file_data; sid:1;) */
1669     if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
1670         if (s->init_data->smlists[s->init_data->list] == NULL) {
1671             SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u setup buffer %s but didn't add matches to it",
1672                     s->id, DetectBufferTypeGetNameById(de_ctx, s->init_data->list));
1673             SCReturnInt(0);
1674         }
1675     }
1676 
1677     /* run buffer type validation callbacks if any */
1678     if (s->init_data->smlists[DETECT_SM_LIST_PMATCH]) {
1679         if (DetectContentPMATCHValidateCallback(s) == FALSE)
1680             SCReturnInt(0);
1681     }
1682 
1683     struct BufferVsDir {
1684         int ts;
1685         int tc;
1686     } bufdir[nlists];
1687     memset(&bufdir, 0, nlists * sizeof(struct BufferVsDir));
1688 
1689     int x;
1690     for (x = 0; x < nlists; x++) {
1691         if (s->init_data->smlists[x]) {
1692             const DetectEngineAppInspectionEngine *app = de_ctx->app_inspect_engines;
1693             for ( ; app != NULL; app = app->next) {
1694                 if (app->sm_list == x &&
1695                         (AppProtoEquals(s->alproto, app->alproto) || s->alproto == 0)) {
1696                     SCLogDebug("engine %s dir %d alproto %d",
1697                             DetectBufferTypeGetNameById(de_ctx, app->sm_list),
1698                             app->dir, app->alproto);
1699 
1700                     bufdir[x].ts += (app->dir == 0);
1701                     bufdir[x].tc += (app->dir == 1);
1702                 }
1703             }
1704 
1705             if (DetectBufferRunValidateCallback(de_ctx, x, s, &de_ctx->sigerror) == FALSE) {
1706                 SCReturnInt(0);
1707             }
1708         }
1709     }
1710 
1711     int ts_excl = 0;
1712     int tc_excl = 0;
1713     int dir_amb = 0;
1714     for (x = 0; x < nlists; x++) {
1715         if (bufdir[x].ts == 0 && bufdir[x].tc == 0)
1716             continue;
1717         ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
1718         tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
1719         dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
1720 
1721         SCLogDebug("%s/%d: %d/%d", DetectBufferTypeGetNameById(de_ctx, x),
1722                 x, bufdir[x].ts, bufdir[x].tc);
1723     }
1724     if (ts_excl && tc_excl) {
1725         SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1726         SCReturnInt(0);
1727     } else if (ts_excl) {
1728         SCLogDebug("%u: implied rule direction is toserver", s->id);
1729         if (DetectFlowSetupImplicit(s, SIG_FLAG_TOSERVER) < 0) {
1730             SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1731             SCReturnInt(0);
1732         }
1733     } else if (tc_excl) {
1734         SCLogDebug("%u: implied rule direction is toclient", s->id);
1735         if (DetectFlowSetupImplicit(s, SIG_FLAG_TOCLIENT) < 0) {
1736             SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
1737             SCReturnInt(0);
1738         }
1739     } else if (dir_amb) {
1740         SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id);
1741     }
1742 
1743     if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
1744         (s->flags & SIG_FLAG_REQUIRE_STREAM)) {
1745         SCLogError(SC_ERR_INVALID_SIGNATURE, "can't mix packet keywords with "
1746                    "tcp-stream or flow:only_stream.  Invalidating signature.");
1747         SCReturnInt(0);
1748     }
1749 
1750 #if 0 // TODO figure out why this is even necessary
1751     if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_SMTP) ||
1752         s->init_data->smlists[DETECT_SM_LIST_UMATCH] != NULL ||
1753         s->init_data->smlists[DETECT_SM_LIST_HRUDMATCH] != NULL ||
1754         s->init_data->smlists[DETECT_SM_LIST_HCBDMATCH] != NULL ||
1755         s->init_data->smlists[DETECT_SM_LIST_HUADMATCH] != NULL) {
1756         sig_flags |= SIG_FLAG_TOSERVER;
1757         s->flags |= SIG_FLAG_TOSERVER;
1758         s->flags &= ~SIG_FLAG_TOCLIENT;
1759     }
1760     if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_HTTP) ||
1761         s->init_data->smlists[DETECT_SM_LIST_HSMDMATCH] != NULL ||
1762         s->init_data->smlists[DETECT_SM_LIST_HSCDMATCH] != NULL) {
1763         sig_flags |= SIG_FLAG_TOCLIENT;
1764         s->flags |= SIG_FLAG_TOCLIENT;
1765         s->flags &= ~SIG_FLAG_TOSERVER;
1766     }
1767 #endif
1768     if ((sig_flags & (SIG_FLAG_TOCLIENT | SIG_FLAG_TOSERVER)) == (SIG_FLAG_TOCLIENT | SIG_FLAG_TOSERVER)) {
1769         SCLogError(SC_ERR_INVALID_SIGNATURE,"You seem to have mixed keywords "
1770                    "that require inspection in both directions.  Atm we only "
1771                    "support keywords in one direction within a rule.");
1772         SCReturnInt(0);
1773     }
1774 
1775     if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1776         for (int i = 0; i < nlists; i++) {
1777             if (s->init_data->smlists[i] == NULL)
1778                 continue;
1779             if (!(DetectBufferTypeGetNameById(de_ctx, i)))
1780                 continue;
1781 
1782             if (!(DetectBufferTypeSupportsPacketGetById(de_ctx, i))) {
1783                 SCLogError(SC_ERR_INVALID_SIGNATURE, "Signature combines packet "
1784                         "specific matches (like dsize, flags, ttl) with stream / "
1785                         "state matching by matching on app layer proto (like using "
1786                         "http_* keywords).");
1787                 SCReturnInt(0);
1788             }
1789         }
1790     }
1791 
1792     /* TCP: corner cases:
1793      * - pkt vs stream vs depth/offset
1794      * - pkt vs stream vs stream_size
1795      */
1796     if (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))) {
1797         if (s->init_data->smlists[DETECT_SM_LIST_PMATCH]) {
1798             if (!(s->flags & (SIG_FLAG_REQUIRE_PACKET | SIG_FLAG_REQUIRE_STREAM))) {
1799                 s->flags |= SIG_FLAG_REQUIRE_STREAM;
1800                 sm = s->init_data->smlists[DETECT_SM_LIST_PMATCH];
1801                 while (sm != NULL) {
1802                     if (sm->type == DETECT_CONTENT &&
1803                             (((DetectContentData *)(sm->ctx))->flags &
1804                              (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET))) {
1805                         s->flags |= SIG_FLAG_REQUIRE_PACKET;
1806                         break;
1807                     }
1808                     sm = sm->next;
1809                 }
1810                 /* if stream_size is in use, also inspect packets */
1811                 sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
1812                 while (sm != NULL) {
1813                     if (sm->type == DETECT_STREAM_SIZE) {
1814                         s->flags |= SIG_FLAG_REQUIRE_PACKET;
1815                         break;
1816                     }
1817                     sm = sm->next;
1818                 }
1819             }
1820         }
1821     }
1822 
1823     if (s->init_data->smlists[DETECT_SM_LIST_BASE64_DATA] != NULL) {
1824         int list;
1825         uint16_t idx = s->init_data->smlists[DETECT_SM_LIST_BASE64_DATA]->idx;
1826         for (list = 0; list < nlists; list++) {
1827             if (list == DETECT_SM_LIST_POSTMATCH ||
1828                 list == DETECT_SM_LIST_TMATCH ||
1829                 list == DETECT_SM_LIST_SUPPRESS ||
1830                 list == DETECT_SM_LIST_THRESHOLD)
1831             {
1832                 continue;
1833             }
1834 
1835             if (list != DETECT_SM_LIST_BASE64_DATA &&
1836                 s->init_data->smlists[list] != NULL) {
1837                 if (s->init_data->smlists[list]->idx > idx) {
1838                     SCLogError(SC_ERR_INVALID_SIGNATURE, "Rule buffer "
1839                         "cannot be reset after base64_data.");
1840                     SCReturnInt(0);
1841                 }
1842             }
1843         }
1844     }
1845 
1846 #ifdef HAVE_LUA
1847     DetectLuaPostSetup(s);
1848 #endif
1849 
1850 #ifdef DEBUG
1851     int i;
1852     for (i = 0; i < nlists; i++) {
1853         if (s->init_data->smlists[i] != NULL) {
1854             for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1855                 BUG_ON(sm == sm->prev);
1856                 BUG_ON(sm == sm->next);
1857             }
1858         }
1859     }
1860 #endif
1861 
1862     if ((s->flags & SIG_FLAG_FILESTORE) || s->file_flags != 0 ||
1863         (s->init_data->init_flags & SIG_FLAG_INIT_FILEDATA)) {
1864         if (s->alproto != ALPROTO_UNKNOWN &&
1865                 !AppLayerParserSupportsFiles(IPPROTO_TCP, s->alproto))
1866         {
1867             SCLogError(SC_ERR_NO_FILES_FOR_PROTOCOL, "protocol %s doesn't "
1868                     "support file matching", AppProtoToString(s->alproto));
1869             SCReturnInt(0);
1870         }
1871         if (s->alproto == ALPROTO_HTTP2 && (s->file_flags & FILE_SIG_NEED_FILENAME)) {
1872             SCLogError(SC_ERR_NO_FILES_FOR_PROTOCOL,
1873                     "protocol HTTP2 doesn't support file name matching");
1874             SCReturnInt(0);
1875         }
1876 
1877         if (s->alproto == ALPROTO_HTTP) {
1878             AppLayerHtpNeedFileInspection();
1879         }
1880     }
1881     if (s->init_data->init_flags & SIG_FLAG_INIT_DCERPC) {
1882         if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_DCERPC &&
1883                 s->alproto != ALPROTO_SMB) {
1884             SCLogError(SC_ERR_NO_FILES_FOR_PROTOCOL, "protocol %s doesn't support DCERPC keyword",
1885                     AppProtoToString(s->alproto));
1886             SCReturnInt(0);
1887         }
1888     }
1889     SCReturnInt(1);
1890 }
1891 
1892 /**
1893  * \internal
1894  * \brief Helper function for SigInit().
1895  */
SigInitHelper(DetectEngineCtx * de_ctx,const char * sigstr,uint8_t dir)1896 static Signature *SigInitHelper(DetectEngineCtx *de_ctx, const char *sigstr,
1897                                 uint8_t dir)
1898 {
1899     SignatureParser parser;
1900     memset(&parser, 0x00, sizeof(parser));
1901 
1902     Signature *sig = SigAlloc();
1903     if (sig == NULL)
1904         goto error;
1905 
1906     /* default gid to 1 */
1907     sig->gid = 1;
1908 
1909     int ret = SigParse(de_ctx, sig, sigstr, dir, &parser);
1910     if (ret == -3) {
1911         de_ctx->sigerror_silent = true;
1912         de_ctx->sigerror_ok = true;
1913         goto error;
1914     }
1915     else if (ret == -2) {
1916         de_ctx->sigerror_silent = true;
1917         goto error;
1918     } else if (ret < 0) {
1919         goto error;
1920     }
1921 
1922     /* signature priority hasn't been overwritten.  Using default priority */
1923     if (sig->prio == -1)
1924         sig->prio = DETECT_DEFAULT_PRIO;
1925 
1926     sig->num = de_ctx->signum;
1927     de_ctx->signum++;
1928 
1929     if (sig->alproto != ALPROTO_UNKNOWN) {
1930         int override_needed = 0;
1931         if (sig->proto.flags & DETECT_PROTO_ANY) {
1932             sig->proto.flags &= ~DETECT_PROTO_ANY;
1933             memset(sig->proto.proto, 0x00, sizeof(sig->proto.proto));
1934             override_needed = 1;
1935         } else {
1936             override_needed = 1;
1937             size_t s = 0;
1938             for (s = 0; s < sizeof(sig->proto.proto); s++) {
1939                 if (sig->proto.proto[s] != 0x00) {
1940                     override_needed = 0;
1941                     break;
1942                 }
1943             }
1944         }
1945 
1946         /* at this point if we had alert ip and the ip proto was not
1947          * overridden, we use the ip proto that has been configured
1948          * against the app proto in use. */
1949         if (override_needed)
1950             AppLayerProtoDetectSupportedIpprotos(sig->alproto, sig->proto.proto);
1951     }
1952 
1953     ret = DetectAppLayerEventPrepare(de_ctx, sig);
1954     if (ret == -3) {
1955         de_ctx->sigerror_silent = true;
1956         de_ctx->sigerror_ok = true;
1957         goto error;
1958     }
1959     else if (ret == -2) {
1960         de_ctx->sigerror_silent = true;
1961         goto error;
1962     } else if (ret < 0) {
1963         goto error;
1964     }
1965 
1966     /* set the packet and app layer flags, but only if the
1967      * app layer flag wasn't already set in which case we
1968      * only consider the app layer */
1969     if (!(sig->flags & SIG_FLAG_APPLAYER)) {
1970         if (sig->init_data->smlists[DETECT_SM_LIST_MATCH] != NULL) {
1971             SigMatch *sm = sig->init_data->smlists[DETECT_SM_LIST_MATCH];
1972             for ( ; sm != NULL; sm = sm->next) {
1973                 if (sigmatch_table[sm->type].Match != NULL)
1974                     sig->init_data->init_flags |= SIG_FLAG_INIT_PACKET;
1975             }
1976         } else {
1977             sig->init_data->init_flags |= SIG_FLAG_INIT_PACKET;
1978         }
1979     }
1980 
1981     if (!(sig->init_data->init_flags & SIG_FLAG_INIT_FLOW)) {
1982         if ((sig->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1983             sig->flags |= SIG_FLAG_TOSERVER;
1984             sig->flags |= SIG_FLAG_TOCLIENT;
1985         }
1986     }
1987 
1988     SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
1989         sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
1990         sig->init_data->init_flags & SIG_FLAG_INIT_PACKET ? "set" : "not set");
1991 
1992     SigBuildAddressMatchArray(sig);
1993 
1994     /* run buffer type callbacks if any */
1995     for (uint32_t x = 0; x < sig->init_data->smlists_array_size; x++) {
1996         if (sig->init_data->smlists[x])
1997             DetectBufferRunSetupCallback(de_ctx, x, sig);
1998     }
1999 
2000     /* validate signature, SigValidate will report the error reason */
2001     if (SigValidate(de_ctx, sig) == 0) {
2002         goto error;
2003     }
2004 
2005     /* check what the type of this sig is */
2006     SignatureSetType(de_ctx, sig);
2007 
2008     if (sig->flags & SIG_FLAG_IPONLY) {
2009         /* For IPOnly */
2010         if (IPOnlySigParseAddress(de_ctx, sig, parser.src, SIG_DIREC_SRC ^ dir) < 0)
2011             goto error;
2012 
2013         if (IPOnlySigParseAddress(de_ctx, sig, parser.dst, SIG_DIREC_DST ^ dir) < 0)
2014             goto error;
2015     }
2016     return sig;
2017 
2018 error:
2019     if (sig != NULL) {
2020         SigFree(de_ctx, sig);
2021     }
2022     return NULL;
2023 }
2024 
2025 /**
2026  * \brief Checks if a signature has the same source and destination
2027  * \param s parsed signature
2028  *
2029  *  \retval true if source and destination are the same, false otherwise
2030  */
SigHasSameSourceAndDestination(const Signature * s)2031 static bool SigHasSameSourceAndDestination(const Signature *s)
2032 {
2033     if (!(s->flags & SIG_FLAG_SP_ANY) || !(s->flags & SIG_FLAG_DP_ANY)) {
2034         if (!DetectPortListsAreEqual(s->sp, s->dp)) {
2035             return false;
2036         }
2037     }
2038 
2039     if (!(s->flags & SIG_FLAG_SRC_ANY) || !(s->flags & SIG_FLAG_DST_ANY)) {
2040         DetectAddress *src = s->init_data->src->ipv4_head;
2041         DetectAddress *dst = s->init_data->dst->ipv4_head;
2042 
2043         if (!DetectAddressListsAreEqual(src, dst)) {
2044             return false;
2045         }
2046 
2047         src = s->init_data->src->ipv6_head;
2048         dst = s->init_data->dst->ipv6_head;
2049 
2050         if (!DetectAddressListsAreEqual(src, dst)) {
2051             return false;
2052         }
2053     }
2054 
2055     return true;
2056 }
2057 
2058 /**
2059  * \brief Parses a signature and adds it to the Detection Engine Context.
2060  *
2061  * \param de_ctx Pointer to the Detection Engine Context.
2062  * \param sigstr Pointer to a character string containing the signature to be
2063  *               parsed.
2064  *
2065  * \retval Pointer to the Signature instance on success; NULL on failure.
2066  */
SigInit(DetectEngineCtx * de_ctx,const char * sigstr)2067 Signature *SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
2068 {
2069     SCEnter();
2070 
2071     uint32_t oldsignum = de_ctx->signum;
2072     de_ctx->sigerror_silent = false;
2073 
2074     Signature *sig;
2075 
2076     if ((sig = SigInitHelper(de_ctx, sigstr, SIG_DIREC_NORMAL)) == NULL) {
2077         goto error;
2078     }
2079 
2080     if (sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2081         if (SigHasSameSourceAndDestination(sig)) {
2082             SCLogInfo("Rule with ID %u is bidirectional, but source and destination are the same, "
2083                 "treating the rule as unidirectional", sig->id);
2084 
2085             sig->init_data->init_flags &= ~SIG_FLAG_INIT_BIDIREC;
2086         } else {
2087             sig->next = SigInitHelper(de_ctx, sigstr, SIG_DIREC_SWITCHED);
2088             if (sig->next == NULL) {
2089                 goto error;
2090             }
2091         }
2092     }
2093 
2094     SCReturnPtr(sig, "Signature");
2095 
2096 error:
2097     if (sig != NULL) {
2098         SigFree(de_ctx, sig);
2099     }
2100     /* if something failed, restore the old signum count
2101      * since we didn't install it */
2102     de_ctx->signum = oldsignum;
2103 
2104     SCReturnPtr(NULL, "Signature");
2105 }
2106 
2107 /**
2108  * \brief The hash free function to be the used by the hash table -
2109  *        DetectEngineCtx->dup_sig_hash_table.
2110  *
2111  * \param data    Pointer to the data, in our case SigDuplWrapper to be freed.
2112  */
DetectParseDupSigFreeFunc(void * data)2113 static void DetectParseDupSigFreeFunc(void *data)
2114 {
2115     if (data != NULL)
2116         SCFree(data);
2117 
2118     return;
2119 }
2120 
2121 /**
2122  * \brief The hash function to be the used by the hash table -
2123  *        DetectEngineCtx->dup_sig_hash_table.
2124  *
2125  * \param ht      Pointer to the hash table.
2126  * \param data    Pointer to the data, in our case SigDuplWrapper.
2127  * \param datalen Not used in our case.
2128  *
2129  * \retval sw->s->id The generated hash value.
2130  */
DetectParseDupSigHashFunc(HashListTable * ht,void * data,uint16_t datalen)2131 static uint32_t DetectParseDupSigHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2132 {
2133     SigDuplWrapper *sw = (SigDuplWrapper *)data;
2134 
2135     return (sw->s->id % ht->array_size);
2136 }
2137 
2138 /**
2139  * \brief The Compare function to be used by the  hash table -
2140  *        DetectEngineCtx->dup_sig_hash_table.
2141  *
2142  * \param data1 Pointer to the first SigDuplWrapper.
2143  * \param len1  Not used.
2144  * \param data2 Pointer to the second SigDuplWrapper.
2145  * \param len2  Not used.
2146  *
2147  * \retval 1 If the 2 SigDuplWrappers sent as args match.
2148  * \retval 0 If the 2 SigDuplWrappers sent as args do not match.
2149  */
DetectParseDupSigCompareFunc(void * data1,uint16_t len1,void * data2,uint16_t len2)2150 static char DetectParseDupSigCompareFunc(void *data1, uint16_t len1, void *data2,
2151                                   uint16_t len2)
2152 {
2153     SigDuplWrapper *sw1 = (SigDuplWrapper *)data1;
2154     SigDuplWrapper *sw2 = (SigDuplWrapper *)data2;
2155 
2156     if (sw1 == NULL || sw2 == NULL ||
2157         sw1->s == NULL || sw2->s == NULL)
2158         return 0;
2159 
2160     /* sid and gid match required */
2161     if (sw1->s->id == sw2->s->id && sw1->s->gid == sw2->s->gid) return 1;
2162 
2163     return 0;
2164 }
2165 
2166 /**
2167  * \brief Initializes the hash table that is used to cull duplicate sigs.
2168  *
2169  * \param de_ctx Pointer to the detection engine context.
2170  *
2171  * \retval  0 On success.
2172  * \retval -1 On failure.
2173  */
DetectParseDupSigHashInit(DetectEngineCtx * de_ctx)2174 int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
2175 {
2176     de_ctx->dup_sig_hash_table = HashListTableInit(15000,
2177                                                    DetectParseDupSigHashFunc,
2178                                                    DetectParseDupSigCompareFunc,
2179                                                    DetectParseDupSigFreeFunc);
2180     if (de_ctx->dup_sig_hash_table == NULL)
2181         return -1;
2182 
2183     return 0;
2184 }
2185 
2186 /**
2187  * \brief Frees the hash table that is used to cull duplicate sigs.
2188  *
2189  * \param de_ctx Pointer to the detection engine context that holds this table.
2190  */
DetectParseDupSigHashFree(DetectEngineCtx * de_ctx)2191 void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
2192 {
2193     if (de_ctx->dup_sig_hash_table != NULL)
2194         HashListTableFree(de_ctx->dup_sig_hash_table);
2195 
2196     de_ctx->dup_sig_hash_table = NULL;
2197 
2198     return;
2199 }
2200 
2201 /**
2202  * \brief Check if a signature is a duplicate.
2203  *
2204  *        There are 3 types of return values for this function.
2205  *
2206  *        - 0, which indicates that the Signature is not a duplicate
2207  *          and has to be added to the detection engine list.
2208  *        - 1, Signature is duplicate, and the existing signature in
2209  *          the list shouldn't be replaced with this duplicate.
2210  *        - 2, Signature is duplicate, and the existing signature in
2211  *          the list should be replaced with this duplicate.
2212  *
2213  * \param de_ctx Pointer to the detection engine context.
2214  * \param sig    Pointer to the Signature that has to be checked.
2215  *
2216  * \retval 2 If Signature is duplicate and the existing signature in
2217  *           the list should be chucked out and replaced with this.
2218  * \retval 1 If Signature is duplicate, and should be chucked out.
2219  * \retval 0 If Signature is not a duplicate.
2220  */
DetectEngineSignatureIsDuplicate(DetectEngineCtx * de_ctx,Signature * sig)2221 static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx,
2222                                                    Signature *sig)
2223 {
2224     /* we won't do any NULL checks on the args */
2225 
2226     /* return value */
2227     int ret = 0;
2228 
2229     SigDuplWrapper *sw_dup = NULL;
2230     SigDuplWrapper *sw = NULL;
2231 
2232     /* used for making a duplicate_sig_hash_table entry */
2233     sw = SCMalloc(sizeof(SigDuplWrapper));
2234     if (unlikely(sw == NULL)) {
2235         exit(EXIT_FAILURE);
2236     }
2237     memset(sw, 0, sizeof(SigDuplWrapper));
2238     sw->s = sig;
2239 
2240     /* check if we have a duplicate entry for this signature */
2241     sw_dup = HashListTableLookup(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2242     /* we don't have a duplicate entry for this sig */
2243     if (sw_dup == NULL) {
2244         /* add it to the hash table */
2245         HashListTableAdd(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2246 
2247         /* add the s_prev entry for the previously loaded sw in the hash_table */
2248         if (de_ctx->sig_list != NULL) {
2249             SigDuplWrapper *sw_old = NULL;
2250             SigDuplWrapper sw_tmp;
2251             memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2252 
2253             /* the topmost sig would be the last loaded sig */
2254             sw_tmp.s = de_ctx->sig_list;
2255             sw_old = HashListTableLookup(de_ctx->dup_sig_hash_table,
2256                                          (void *)&sw_tmp, 0);
2257             /* sw_old == NULL case is impossible */
2258             sw_old->s_prev = sig;
2259         }
2260 
2261         ret = 0;
2262         goto end;
2263     }
2264 
2265     /* if we have reached here we have a duplicate entry for this signature.
2266      * Check the signature revision.  Store the signature with the latest rev
2267      * and discard the other one */
2268     if (sw->s->rev <= sw_dup->s->rev) {
2269         ret = 1;
2270         SCFree(sw);
2271         sw = NULL;
2272         goto end;
2273     }
2274 
2275     /* the new sig is of a newer revision than the one that is already in the
2276      * list.  Remove the old sig from the list */
2277     if (sw_dup->s_prev == NULL) {
2278         SigDuplWrapper sw_temp;
2279         memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2280         if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2281             sw_temp.s = sw_dup->s->next->next;
2282             de_ctx->sig_list = sw_dup->s->next->next;
2283             SigFree(de_ctx, sw_dup->s->next);
2284         } else {
2285             sw_temp.s = sw_dup->s->next;
2286             de_ctx->sig_list = sw_dup->s->next;
2287         }
2288         SigDuplWrapper *sw_next = NULL;
2289         if (sw_temp.s != NULL) {
2290             sw_next = HashListTableLookup(de_ctx->dup_sig_hash_table,
2291                                           (void *)&sw_temp, 0);
2292             sw_next->s_prev = sw_dup->s_prev;
2293         }
2294         SigFree(de_ctx, sw_dup->s);
2295     } else {
2296         SigDuplWrapper sw_temp;
2297         memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2298         if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2299             sw_temp.s = sw_dup->s->next->next;
2300             /* If previous signature is bidirectional,
2301              * it has 2 items in the linked list.
2302              * So we need to change next->next instead of next
2303              */
2304             if (sw_dup->s_prev->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2305                 sw_dup->s_prev->next->next = sw_dup->s->next->next;
2306             } else {
2307                 sw_dup->s_prev->next = sw_dup->s->next->next;
2308             }
2309             SigFree(de_ctx, sw_dup->s->next);
2310         } else {
2311             sw_temp.s = sw_dup->s->next;
2312             if (sw_dup->s_prev->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2313                 sw_dup->s_prev->next->next = sw_dup->s->next;
2314             } else {
2315                 sw_dup->s_prev->next = sw_dup->s->next;
2316             }
2317         }
2318         SigDuplWrapper *sw_next = NULL;
2319         if (sw_temp.s != NULL) {
2320             sw_next = HashListTableLookup(de_ctx->dup_sig_hash_table,
2321                                           (void *)&sw_temp, 0);
2322             sw_next->s_prev = sw_dup->s_prev;;
2323         }
2324         SigFree(de_ctx, sw_dup->s);
2325     }
2326 
2327     /* make changes to the entry to reflect the presence of the new sig */
2328     sw_dup->s = sig;
2329     sw_dup->s_prev = NULL;
2330 
2331     if (de_ctx->sig_list != NULL) {
2332         SigDuplWrapper sw_tmp;
2333         memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2334         sw_tmp.s = de_ctx->sig_list;
2335         SigDuplWrapper *sw_old = HashListTableLookup(de_ctx->dup_sig_hash_table,
2336                                                      (void *)&sw_tmp, 0);
2337         if (sw_old->s != sw_dup->s) {
2338             // Link on top of the list if there was another element
2339             sw_old->s_prev = sig;
2340         }
2341     }
2342 
2343     /* this is duplicate, but a duplicate that replaced the existing sig entry */
2344     ret = 2;
2345 
2346     SCFree(sw);
2347 
2348 end:
2349     return ret;
2350 }
2351 
2352 /**
2353  * \brief Parse and append a Signature into the Detection Engine Context
2354  *        signature list.
2355  *
2356  *        If the signature is bidirectional it should append two signatures
2357  *        (with the addresses switched) into the list.  Also handle duplicate
2358  *        signatures.  In case of duplicate sigs, use the ones that have the
2359  *        latest revision.  We use the sid and the msg to identify duplicate
2360  *        sigs.  If 2 sigs have the same sid and gid, they are duplicates.
2361  *
2362  * \param de_ctx Pointer to the Detection Engine Context.
2363  * \param sigstr Pointer to a character string containing the signature to be
2364  *               parsed.
2365  * \param sig_file Pointer to a character string containing the filename from
2366  *                 which signature is read
2367  * \param lineno Line number from where signature is read
2368  *
2369  * \retval Pointer to the head Signature in the detection engine ctx sig_list
2370  *         on success; NULL on failure.
2371  */
DetectEngineAppendSig(DetectEngineCtx * de_ctx,const char * sigstr)2372 Signature *DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
2373 {
2374     Signature *sig = SigInit(de_ctx, sigstr);
2375     if (sig == NULL) {
2376         return NULL;
2377     }
2378 
2379     /* checking for the status of duplicate signature */
2380     int dup_sig = DetectEngineSignatureIsDuplicate(de_ctx, sig);
2381     /* a duplicate signature that should be chucked out.  Check the previously
2382      * called function details to understand the different return values */
2383     if (dup_sig == 1) {
2384         SCLogError(SC_ERR_DUPLICATE_SIG, "Duplicate signature \"%s\"", sigstr);
2385         goto error;
2386     } else if (dup_sig == 2) {
2387         SCLogWarning(SC_ERR_DUPLICATE_SIG, "Signature with newer revision,"
2388                 " so the older sig replaced by this new signature \"%s\"",
2389                 sigstr);
2390     }
2391 
2392     if (sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2393         if (sig->next != NULL) {
2394             sig->next->next = de_ctx->sig_list;
2395         } else {
2396             goto error;
2397         }
2398     } else {
2399         /* if this sig is the first one, sig_list should be null */
2400         sig->next = de_ctx->sig_list;
2401     }
2402 
2403     de_ctx->sig_list = sig;
2404 
2405     /**
2406      * In DetectEngineAppendSig(), the signatures are prepended and we always return the first one
2407      * so if the signature is bidirectional, the returned sig will point through "next" ptr
2408      * to the cloned signatures with the switched addresses
2409      */
2410     return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
2411 
2412 error:
2413     /* free the 2nd sig bidir may have set up */
2414     if (sig != NULL && sig->next != NULL) {
2415         SigFree(de_ctx, sig->next);
2416         sig->next = NULL;
2417     }
2418     if (sig != NULL) {
2419         SigFree(de_ctx, sig);
2420     }
2421     return NULL;
2422 }
2423 
2424 static DetectParseRegex *g_detect_parse_regex_list = NULL;
DetectParsePcreExecLen(DetectParseRegex * parse_regex,const char * str,int str_len,int start_offset,int options,int * ovector,int ovector_size)2425 int DetectParsePcreExecLen(DetectParseRegex *parse_regex, const char *str,
2426                    int str_len,
2427                    int start_offset, int options,
2428                    int *ovector, int ovector_size)
2429 {
2430     return pcre_exec(parse_regex->regex, parse_regex->study, str, str_len,
2431                      start_offset, options, ovector, ovector_size);
2432 }
2433 
DetectParsePcreExec(DetectParseRegex * parse_regex,const char * str,int start_offset,int options,int * ovector,int ovector_size)2434 int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str,
2435                    int start_offset, int options,
2436                    int *ovector, int ovector_size)
2437 {
2438     return pcre_exec(parse_regex->regex, parse_regex->study, str, strlen(str),
2439                      start_offset, options, ovector, ovector_size);
2440 }
2441 
DetectParseFreeRegex(DetectParseRegex * r)2442 void DetectParseFreeRegex(DetectParseRegex *r)
2443 {
2444     if (r->regex) {
2445         pcre_free(r->regex);
2446     }
2447     if (r->study) {
2448         pcre_free_study(r->study);
2449     }
2450 }
2451 
DetectParseFreeRegexes(void)2452 void DetectParseFreeRegexes(void)
2453 {
2454     DetectParseRegex *r = g_detect_parse_regex_list;
2455     while (r) {
2456         DetectParseRegex *next = r->next;
2457 
2458         DetectParseFreeRegex(r);
2459 
2460         SCFree(r);
2461         r = next;
2462     }
2463     g_detect_parse_regex_list = NULL;
2464 }
2465 
2466 /** \brief add regex and/or study to at exit free list
2467  */
DetectParseRegexAddToFreeList(DetectParseRegex * detect_parse)2468 void DetectParseRegexAddToFreeList(DetectParseRegex *detect_parse)
2469 {
2470     DetectParseRegex *r = SCCalloc(1, sizeof(*r));
2471     if (r == NULL) {
2472         FatalError(SC_ERR_MEM_ALLOC, "failed to alloc memory for pcre free list");
2473     }
2474     r->regex = detect_parse->regex;
2475     r->study = detect_parse->study;
2476     r->next = g_detect_parse_regex_list;
2477     g_detect_parse_regex_list = r;
2478 }
2479 
DetectSetupParseRegexesOpts(const char * parse_str,DetectParseRegex * detect_parse,int opts)2480 bool DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *detect_parse, int opts)
2481 {
2482     const char *eb = NULL;
2483     int eo;
2484 
2485     detect_parse->regex = pcre_compile(parse_str, opts, &eb, &eo, NULL);
2486     if (detect_parse->regex == NULL) {
2487         SCLogError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at "
2488                 "offset %" PRId32 ": %s", parse_str, eo, eb);
2489         return false;
2490     }
2491 
2492     detect_parse->study = pcre_study(detect_parse->regex, 0 , &eb);
2493     if (eb != NULL) {
2494         SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
2495         return false;
2496     }
2497 
2498 
2499     DetectParseRegexAddToFreeList(detect_parse);
2500 
2501     return true;
2502 }
2503 
DetectSetupParseRegexes(const char * parse_str,DetectParseRegex * detect_parse)2504 void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
2505 {
2506     if (!DetectSetupParseRegexesOpts(parse_str, detect_parse, 0)) {
2507         FatalError(SC_ERR_PCRE_COMPILE, "pcre compile and study failed");
2508     }
2509 }
2510 
2511 
2512 /*
2513  * TESTS
2514  */
2515 
2516 #ifdef UNITTESTS
SigParseTest01(void)2517 static int SigParseTest01 (void)
2518 {
2519     int result = 1;
2520     Signature *sig = NULL;
2521 
2522     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2523     if (de_ctx == NULL)
2524         goto end;
2525 
2526     sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
2527     if (sig == NULL)
2528         result = 0;
2529 
2530 end:
2531     if (sig != NULL) SigFree(de_ctx, sig);
2532     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2533     return result;
2534 }
2535 
SigParseTest02(void)2536 static int SigParseTest02 (void)
2537 {
2538     int result = 0;
2539     Signature *sig = NULL;
2540     DetectPort *port = NULL;
2541 
2542     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2543 
2544     if (de_ctx == NULL)
2545         goto end;
2546 
2547     FILE *fd = SCClassConfGenerateValidDummyClassConfigFD01();
2548     SCClassConfLoadClassficationConfigFile(de_ctx, fd);
2549 
2550     sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"ET MALWARE Suspicious 220 Banner on Local Port\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:2003055; rev:4;)");
2551     if (sig == NULL) {
2552         goto end;
2553     }
2554 
2555     int r = DetectPortParse(de_ctx, &port, "0:20");
2556     if (r < 0)
2557         goto end;
2558 
2559     if (DetectPortCmp(sig->sp, port) == PORT_EQ) {
2560         result = 1;
2561     } else {
2562         DetectPortPrint(port); printf(" != "); DetectPortPrint(sig->sp); printf(": ");
2563     }
2564 
2565 end:
2566     if (port != NULL)
2567         DetectPortCleanupList(de_ctx, port);
2568     if (sig != NULL)
2569         SigFree(de_ctx, sig);
2570     if (de_ctx != NULL)
2571         DetectEngineCtxFree(de_ctx);
2572     return result;
2573 }
2574 
2575 /**
2576  * \test SigParseTest03 test for invalid direction operator in rule
2577  */
SigParseTest03(void)2578 static int SigParseTest03 (void)
2579 {
2580     int result = 1;
2581     Signature *sig = NULL;
2582 
2583     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2584     if (de_ctx == NULL)
2585         goto end;
2586 
2587     sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any <- !1.2.3.4 any (msg:\"SigParseTest03\"; sid:1;)");
2588     if (sig != NULL) {
2589         result = 0;
2590         printf("expected NULL got sig ptr %p: ",sig);
2591     }
2592 
2593 end:
2594     if (sig != NULL) SigFree(de_ctx, sig);
2595     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2596     return result;
2597 }
2598 
SigParseTest04(void)2599 static int SigParseTest04 (void)
2600 {
2601     int result = 1;
2602     Signature *sig = NULL;
2603 
2604     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2605     if (de_ctx == NULL)
2606         goto end;
2607 
2608     sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024: -> !1.2.3.4 1024: (msg:\"SigParseTest04\"; sid:1;)");
2609     if (sig == NULL)
2610         result = 0;
2611 
2612 end:
2613     if (sig != NULL) SigFree(de_ctx, sig);
2614     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2615     return result;
2616 }
2617 
2618 /** \test Port validation */
SigParseTest05(void)2619 static int SigParseTest05 (void)
2620 {
2621     int result = 0;
2622     Signature *sig = NULL;
2623 
2624     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2625     if (de_ctx == NULL)
2626         goto end;
2627 
2628     sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024:65536 -> !1.2.3.4 any (msg:\"SigParseTest05\"; sid:1;)");
2629     if (sig == NULL) {
2630         result = 1;
2631     } else {
2632         printf("signature didn't fail to parse as we expected: ");
2633     }
2634 
2635 end:
2636     if (sig != NULL) SigFree(de_ctx, sig);
2637     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2638     return result;
2639 }
2640 
2641 /** \test Parsing bug debugging at 2010-03-18 */
SigParseTest06(void)2642 static int SigParseTest06 (void)
2643 {
2644     int result = 0;
2645     Signature *sig = NULL;
2646 
2647     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2648     if (de_ctx == NULL)
2649         goto end;
2650 
2651     sig = SigInit(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"GET\"; nocase; http_method; uricontent:\"/uri/\"; nocase; content:\"Host|3A| abc\"; nocase; sid:1; rev:1;)");
2652     if (sig != NULL) {
2653         result = 1;
2654     } else {
2655         printf("signature failed to parse: ");
2656     }
2657 
2658 end:
2659     if (sig != NULL)
2660         SigFree(de_ctx, sig);
2661     if (de_ctx != NULL)
2662         DetectEngineCtxFree(de_ctx);
2663     return result;
2664 }
2665 
2666 /**
2667  * \test Parsing duplicate sigs.
2668  */
SigParseTest07(void)2669 static int SigParseTest07(void)
2670 {
2671     int result = 0;
2672 
2673     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2674     if (de_ctx == NULL)
2675         goto end;
2676 
2677     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2678     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2679 
2680     result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL);
2681 
2682 end:
2683     if (de_ctx != NULL)
2684         DetectEngineCtxFree(de_ctx);
2685     return result;
2686 }
2687 
2688 /**
2689  * \test Parsing duplicate sigs.
2690  */
SigParseTest08(void)2691 static int SigParseTest08(void)
2692 {
2693     int result = 0;
2694 
2695     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2696     if (de_ctx == NULL)
2697         goto end;
2698 
2699     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2700     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
2701 
2702     result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL &&
2703               de_ctx->sig_list->rev == 2);
2704 
2705 end:
2706     if (de_ctx != NULL)
2707         DetectEngineCtxFree(de_ctx);
2708     return result;
2709 }
2710 
2711 /**
2712  * \test Parsing duplicate sigs.
2713  */
SigParseTest09(void)2714 static int SigParseTest09(void)
2715 {
2716     int result = 1;
2717 
2718     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2719     if (de_ctx == NULL)
2720         goto end;
2721 
2722     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2723     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
2724     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:6;)");
2725     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:4;)");
2726     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
2727     result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2728                de_ctx->sig_list->rev == 2);
2729     if (result == 0)
2730         goto end;
2731     result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2732                de_ctx->sig_list->next->rev == 6);
2733     if (result == 0)
2734         goto end;
2735 
2736     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
2737     result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2738                de_ctx->sig_list->rev == 2);
2739     if (result == 0)
2740         goto end;
2741     result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2742                de_ctx->sig_list->next->rev == 6);
2743     if (result == 0)
2744         goto end;
2745 
2746     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:4;)");
2747     result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
2748                de_ctx->sig_list->rev == 4);
2749     if (result == 0)
2750         goto end;
2751     result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
2752                de_ctx->sig_list->next->rev == 6);
2753     if (result == 0)
2754         goto end;
2755 
2756 end:
2757     if (de_ctx != NULL)
2758         DetectEngineCtxFree(de_ctx);
2759     return result;
2760 }
2761 
2762 /**
2763  * \test Parsing duplicate sigs.
2764  */
SigParseTest10(void)2765 static int SigParseTest10(void)
2766 {
2767     int result = 1;
2768 
2769     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2770     if (de_ctx == NULL)
2771         goto end;
2772 
2773     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
2774     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
2775     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:1;)");
2776     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:4; rev:1;)");
2777     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:5; rev:1;)");
2778     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:2;)");
2779     DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
2780 
2781     result &= ((de_ctx->sig_list->id == 2) &&
2782                (de_ctx->sig_list->next->id == 3) &&
2783                (de_ctx->sig_list->next->next->id == 5) &&
2784                (de_ctx->sig_list->next->next->next->id == 4) &&
2785                (de_ctx->sig_list->next->next->next->next->id == 1));
2786 
2787 end:
2788     if (de_ctx != NULL)
2789         DetectEngineCtxFree(de_ctx);
2790     return result;
2791 }
2792 
2793 /**
2794  * \test Parsing sig with trailing space(s) as reported by
2795  *       Morgan Cox on oisf-users.
2796  */
SigParseTest11(void)2797 static int SigParseTest11(void)
2798 {
2799     int result = 0;
2800 
2801     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2802     if (de_ctx == NULL)
2803         goto end;
2804 
2805     Signature *s = NULL;
2806 
2807     s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\";) ");
2808     if (s == NULL) {
2809         printf("sig 1 didn't parse: ");
2810         goto end;
2811     }
2812 
2813     s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\"; sid:1;)            ");
2814     if (s == NULL) {
2815         printf("sig 2 didn't parse: ");
2816         goto end;
2817     }
2818 
2819     result = 1;
2820 end:
2821     if (de_ctx != NULL)
2822         DetectEngineCtxFree(de_ctx);
2823     return result;
2824 }
2825 
2826 /**
2827  * \test file_data with rawbytes
2828  */
SigParseTest12(void)2829 static int SigParseTest12(void)
2830 {
2831     int result = 0;
2832 
2833     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2834     if (de_ctx == NULL)
2835         goto end;
2836 
2837     Signature *s = NULL;
2838 
2839     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (file_data; content:\"abc\"; rawbytes; sid:1;)");
2840     if (s != NULL) {
2841         printf("sig 1 should have given an error: ");
2842         goto end;
2843     }
2844 
2845     result = 1;
2846 end:
2847     if (de_ctx != NULL)
2848         DetectEngineCtxFree(de_ctx);
2849     return result;
2850 }
2851 
2852 /**
2853  * \test packet/stream sig
2854  */
SigParseTest13(void)2855 static int SigParseTest13(void)
2856 {
2857     int result = 0;
2858 
2859     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2860     if (de_ctx == NULL)
2861         goto end;
2862 
2863     Signature *s = NULL;
2864 
2865     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; sid:1;)");
2866     if (s == NULL) {
2867         printf("sig 1 invalidated: failure");
2868         goto end;
2869     }
2870 
2871     if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2872         printf("sig doesn't have stream flag set\n");
2873         goto end;
2874     }
2875 
2876     if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
2877         printf("sig has packet flag set\n");
2878         goto end;
2879     }
2880 
2881     result = 1;
2882 
2883 end:
2884     if (de_ctx != NULL)
2885         DetectEngineCtxFree(de_ctx);
2886     return result;
2887 }
2888 
2889 /**
2890  * \test packet/stream sig
2891  */
SigParseTest14(void)2892 static int SigParseTest14(void)
2893 {
2894     int result = 0;
2895 
2896     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2897     if (de_ctx == NULL)
2898         goto end;
2899 
2900     Signature *s = NULL;
2901 
2902     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; dsize:>0; sid:1;)");
2903     if (s == NULL) {
2904         printf("sig 1 invalidated: failure");
2905         goto end;
2906     }
2907 
2908     if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2909         printf("sig doesn't have packet flag set\n");
2910         goto end;
2911     }
2912 
2913     if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
2914         printf("sig has stream flag set\n");
2915         goto end;
2916     }
2917 
2918     result = 1;
2919 
2920 end:
2921     if (de_ctx != NULL)
2922         DetectEngineCtxFree(de_ctx);
2923     return result;
2924 }
2925 
2926 /**
2927  * \test packet/stream sig
2928  */
SigParseTest15(void)2929 static int SigParseTest15(void)
2930 {
2931     int result = 0;
2932 
2933     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2934     if (de_ctx == NULL)
2935         goto end;
2936 
2937     Signature *s = NULL;
2938 
2939     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:5; sid:1;)");
2940     if (s == NULL) {
2941         printf("sig 1 invalidated: failure");
2942         goto end;
2943     }
2944 
2945     if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2946         printf("sig doesn't have packet flag set\n");
2947         goto end;
2948     }
2949 
2950     if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2951         printf("sig doesn't have stream flag set\n");
2952         goto end;
2953     }
2954 
2955     result = 1;
2956 
2957 end:
2958     if (de_ctx != NULL)
2959         DetectEngineCtxFree(de_ctx);
2960     return result;
2961 }
2962 
2963 /**
2964  * \test packet/stream sig
2965  */
SigParseTest16(void)2966 static int SigParseTest16(void)
2967 {
2968     int result = 0;
2969 
2970     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2971     if (de_ctx == NULL)
2972         goto end;
2973 
2974     Signature *s = NULL;
2975 
2976     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; depth:5; sid:1;)");
2977     if (s == NULL) {
2978         printf("sig 1 invalidated: failure");
2979         goto end;
2980     }
2981 
2982     if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
2983         printf("sig doesn't have packet flag set\n");
2984         goto end;
2985     }
2986 
2987     if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2988         printf("sig doesn't have stream flag set\n");
2989         goto end;
2990     }
2991 
2992     result = 1;
2993 
2994 end:
2995     if (de_ctx != NULL)
2996         DetectEngineCtxFree(de_ctx);
2997     return result;
2998 }
2999 
3000 /**
3001  * \test packet/stream sig
3002  */
SigParseTest17(void)3003 static int SigParseTest17(void)
3004 {
3005     int result = 0;
3006 
3007     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3008     if (de_ctx == NULL)
3009         goto end;
3010 
3011     Signature *s = NULL;
3012 
3013     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)");
3014     if (s == NULL) {
3015         printf("sig 1 invalidated: failure");
3016         goto end;
3017     }
3018 
3019     if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3020         printf("sig doesn't have packet flag set\n");
3021         goto end;
3022     }
3023 
3024     if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3025         printf("sig doesn't have stream flag set\n");
3026         goto end;
3027     }
3028 
3029     result = 1;
3030 
3031 end:
3032     if (de_ctx != NULL)
3033         DetectEngineCtxFree(de_ctx);
3034     return result;
3035 }
3036 
3037 /** \test sid value too large. Bug #779 */
SigParseTest18(void)3038 static int SigParseTest18 (void)
3039 {
3040     int result = 0;
3041 
3042     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3043     if (de_ctx == NULL)
3044         goto end;
3045 
3046     if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:99999999999999999999;)") != NULL)
3047         goto end;
3048 
3049     result = 1;
3050 end:
3051     if (de_ctx != NULL)
3052         DetectEngineCtxFree(de_ctx);
3053     return result;
3054 }
3055 
3056 /** \test gid value too large. Related to bug #779 */
SigParseTest19(void)3057 static int SigParseTest19 (void)
3058 {
3059     int result = 0;
3060 
3061     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3062     if (de_ctx == NULL)
3063         goto end;
3064 
3065     if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; gid:99999999999999999999;)") != NULL)
3066         goto end;
3067 
3068     result = 1;
3069 end:
3070     if (de_ctx != NULL)
3071         DetectEngineCtxFree(de_ctx);
3072     return result;
3073 }
3074 
3075 /** \test rev value too large. Related to bug #779 */
SigParseTest20(void)3076 static int SigParseTest20 (void)
3077 {
3078     int result = 0;
3079 
3080     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3081     if (de_ctx == NULL)
3082         goto end;
3083 
3084     if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; rev:99999999999999999999;)") != NULL)
3085         goto end;
3086 
3087     result = 1;
3088 end:
3089     if (de_ctx != NULL)
3090         DetectEngineCtxFree(de_ctx);
3091     return result;
3092 }
3093 
3094 /** \test address parsing */
SigParseTest21(void)3095 static int SigParseTest21 (void)
3096 {
3097     int result = 0;
3098 
3099     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3100     if (de_ctx == NULL)
3101         goto end;
3102 
3103     if (DetectEngineAppendSig(de_ctx, "alert tcp [1.2.3.4, 1.2.3.5] any -> !1.2.3.4 any (sid:1;)") == NULL)
3104         goto end;
3105 
3106     result = 1;
3107 end:
3108     if (de_ctx != NULL)
3109         DetectEngineCtxFree(de_ctx);
3110     return result;
3111 }
3112 
3113 /** \test address parsing */
SigParseTest22(void)3114 static int SigParseTest22 (void)
3115 {
3116     int result = 0;
3117 
3118     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3119     if (de_ctx == NULL)
3120         goto end;
3121 
3122     if (DetectEngineAppendSig(de_ctx, "alert tcp [10.10.10.0/24, !10.10.10.247] any -> [10.10.10.0/24, !10.10.10.247] any (sid:1;)") == NULL)
3123         goto end;
3124 
3125     result = 1;
3126 end:
3127     if (de_ctx != NULL)
3128         DetectEngineCtxFree(de_ctx);
3129     return result;
3130 }
3131 
3132 /**
3133  * \test rule ending in carriage return
3134  */
SigParseTest23(void)3135 static int SigParseTest23(void)
3136 {
3137     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3138     FAIL_IF_NULL(de_ctx);
3139 
3140     Signature *s = NULL;
3141 
3142     s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)\r");
3143     FAIL_IF_NULL(s);
3144 
3145     DetectEngineCtxFree(de_ctx);
3146     PASS;
3147 }
3148 
3149 /** \test Direction operator validation (invalid) */
SigParseBidirecTest06(void)3150 static int SigParseBidirecTest06 (void)
3151 {
3152     int result = 1;
3153     Signature *sig = NULL;
3154 
3155     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3156     if (de_ctx == NULL)
3157         goto end;
3158 
3159     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any - 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3160     if (sig == NULL)
3161         result = 1;
3162 
3163 end:
3164     if (sig != NULL) SigFree(de_ctx, sig);
3165     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3166     return result;
3167 }
3168 
3169 /** \test Direction operator validation (invalid) */
SigParseBidirecTest07(void)3170 static int SigParseBidirecTest07 (void)
3171 {
3172     int result = 1;
3173     Signature *sig = NULL;
3174 
3175     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3176     if (de_ctx == NULL)
3177         goto end;
3178 
3179     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3180     if (sig == NULL)
3181         result = 1;
3182 
3183 end:
3184     if (sig != NULL) SigFree(de_ctx, sig);
3185     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3186     return result;
3187 }
3188 
3189 /** \test Direction operator validation (invalid) */
SigParseBidirecTest08(void)3190 static int SigParseBidirecTest08 (void)
3191 {
3192     int result = 1;
3193     Signature *sig = NULL;
3194 
3195     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3196     if (de_ctx == NULL)
3197         goto end;
3198 
3199     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any < 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3200     if (sig == NULL)
3201         result = 1;
3202 
3203 end:
3204     if (sig != NULL) SigFree(de_ctx, sig);
3205     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3206     return result;
3207 }
3208 
3209 /** \test Direction operator validation (invalid) */
SigParseBidirecTest09(void)3210 static int SigParseBidirecTest09 (void)
3211 {
3212     int result = 1;
3213     Signature *sig = NULL;
3214 
3215     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3216     if (de_ctx == NULL)
3217         goto end;
3218 
3219     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any > 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3220     if (sig == NULL)
3221         result = 1;
3222 
3223 end:
3224     if (sig != NULL) SigFree(de_ctx, sig);
3225     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3226     return result;
3227 }
3228 
3229 /** \test Direction operator validation (invalid) */
SigParseBidirecTest10(void)3230 static int SigParseBidirecTest10 (void)
3231 {
3232     int result = 1;
3233     Signature *sig = NULL;
3234 
3235     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3236     if (de_ctx == NULL)
3237         goto end;
3238 
3239     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3240     if (sig == NULL)
3241         result = 1;
3242 
3243 end:
3244     if (sig != NULL) SigFree(de_ctx, sig);
3245     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3246     return result;
3247 }
3248 
3249 /** \test Direction operator validation (invalid) */
SigParseBidirecTest11(void)3250 static int SigParseBidirecTest11 (void)
3251 {
3252     int result = 1;
3253     Signature *sig = NULL;
3254 
3255     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3256     if (de_ctx == NULL)
3257         goto end;
3258 
3259     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3260     if (sig == NULL)
3261         result = 1;
3262 
3263 end:
3264     if (sig != NULL) SigFree(de_ctx, sig);
3265     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3266     return result;
3267 }
3268 
3269 /** \test Direction operator validation (invalid) */
SigParseBidirecTest12(void)3270 static int SigParseBidirecTest12 (void)
3271 {
3272     int result = 1;
3273     Signature *sig = NULL;
3274 
3275     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3276     if (de_ctx == NULL)
3277         goto end;
3278 
3279     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3280     if (sig == NULL)
3281         result = 1;
3282 
3283 end:
3284     if (sig != NULL) SigFree(de_ctx, sig);
3285     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3286     return result;
3287 }
3288 
3289 /** \test Direction operator validation (valid) */
SigParseBidirecTest13(void)3290 static int SigParseBidirecTest13 (void)
3291 {
3292     int result = 1;
3293     Signature *sig = NULL;
3294 
3295     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3296     if (de_ctx == NULL)
3297         goto end;
3298 
3299     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3300     if (sig != NULL)
3301         result = 1;
3302 
3303 end:
3304     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3305     return result;
3306 }
3307 
3308 /** \test Direction operator validation (valid) */
SigParseBidirecTest14(void)3309 static int SigParseBidirecTest14 (void)
3310 {
3311     int result = 1;
3312     Signature *sig = NULL;
3313 
3314     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3315     if (de_ctx == NULL)
3316         goto end;
3317 
3318     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3319     if (sig != NULL)
3320         result = 1;
3321 
3322 end:
3323     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3324     return result;
3325 }
3326 
3327 /** \test Ensure that we don't set bidirectional in a
3328  *         normal (one direction) Signature
3329  */
SigTestBidirec01(void)3330 static int SigTestBidirec01 (void)
3331 {
3332     Signature *sig = NULL;
3333     int result = 0;
3334 
3335     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3336     if (de_ctx == NULL)
3337         goto end;
3338 
3339     sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 -> !1.2.3.4 any (msg:\"SigTestBidirec01\"; sid:1;)");
3340     if (sig == NULL)
3341         goto end;
3342     if (sig->next != NULL)
3343         goto end;
3344     if (sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC)
3345         goto end;
3346     if (de_ctx->signum != 1)
3347         goto end;
3348 
3349     result = 1;
3350 
3351 end:
3352     if (de_ctx != NULL) {
3353         SigCleanSignatures(de_ctx);
3354         SigGroupCleanup(de_ctx);
3355         DetectEngineCtxFree(de_ctx);
3356     }
3357     return result;
3358 }
3359 
3360 /** \test Ensure that we set a bidirectional Signature correctly */
SigTestBidirec02(void)3361 static int SigTestBidirec02 (void)
3362 {
3363     int result = 0;
3364     Signature *sig = NULL;
3365     Signature *copy = NULL;
3366 
3367     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3368     if (de_ctx == NULL)
3369         goto end;
3370 
3371     de_ctx->flags |= DE_QUIET;
3372 
3373     sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 <> !1.2.3.4 any (msg:\"SigTestBidirec02\"; sid:1;)");
3374     if (sig == NULL)
3375         goto end;
3376     if (de_ctx->sig_list != sig)
3377         goto end;
3378     if (!(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3379         goto end;
3380     if (sig->next == NULL)
3381         goto end;
3382     if (de_ctx->signum != 2)
3383         goto end;
3384     copy = sig->next;
3385     if (copy->next != NULL)
3386         goto end;
3387     if (!(copy->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3388         goto end;
3389 
3390     result = 1;
3391 
3392 end:
3393     if (de_ctx != NULL) {
3394         SigCleanSignatures(de_ctx);
3395         SigGroupCleanup(de_ctx);
3396         DetectEngineCtxFree(de_ctx);
3397     }
3398 
3399     return result;
3400 }
3401 
3402 /** \test Ensure that we set a bidirectional Signature correctly
3403 *         and we install it with the rest of the signatures, checking
3404 *         also that it match with the correct addr directions
3405 */
SigTestBidirec03(void)3406 static int SigTestBidirec03 (void)
3407 {
3408     int result = 0;
3409     Signature *sig = NULL;
3410     Packet *p = NULL;
3411 
3412     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3413     if (de_ctx == NULL)
3414         goto end;
3415 
3416     de_ctx->flags |= DE_QUIET;
3417 
3418     const char *sigs[3];
3419     sigs[0] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)";
3420     sigs[1] = "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)";
3421     sigs[2] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)";
3422     UTHAppendSigs(de_ctx, sigs, 3);
3423 
3424     /* Checking that bidirectional rules are set correctly */
3425     sig = de_ctx->sig_list;
3426     if (sig == NULL)
3427         goto end;
3428     if (sig->next == NULL)
3429         goto end;
3430     if (sig->next->next == NULL)
3431         goto end;
3432     if (sig->next->next->next == NULL)
3433         goto end;
3434     if (sig->next->next->next->next != NULL)
3435         goto end;
3436     if (de_ctx->signum != 4)
3437         goto end;
3438 
3439     uint8_t rawpkt1_ether[] = {
3440         0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3441         0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3442         0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3443         0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3444         0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3445         0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3446         0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3447         0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3448         0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3449         0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3450         0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3451         0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3452         0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3453         0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3454         0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3455         0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3456         0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3457         0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3458         0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3459         0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3460         0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3461         0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3462         0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3463         0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3464         0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3465         0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3466         0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3467         0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3468         0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3469         0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3470         0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3471         0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3472         0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3473         0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3474         0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3475         0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3476         0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3477         0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3478         0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3479         0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3480         0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3481         0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3482         0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3483         0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3484         0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3485         0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3486         0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3487         0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3488         0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3489         0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3490         0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3491         0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3492         0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3493         0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3494         0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3495 
3496     FlowInitConfig(FLOW_QUIET);
3497     p = UTHBuildPacketFromEth(rawpkt1_ether, sizeof(rawpkt1_ether));
3498     if (p == NULL) {
3499         SCLogDebug("Error building packet");
3500         goto end;
3501     }
3502     UTHMatchPackets(de_ctx, &p, 1);
3503 
3504     uint32_t sids[3] = {1, 2, 3};
3505     uint32_t results[3] = {1, 1, 1};
3506     result = UTHCheckPacketMatchResults(p, sids, results, 1);
3507 
3508 end:
3509     if (p != NULL) {
3510         PACKET_RECYCLE(p);
3511         SCFree(p);
3512     }
3513     if (de_ctx != NULL) {
3514         SigCleanSignatures(de_ctx);
3515         SigGroupCleanup(de_ctx);
3516         DetectEngineCtxFree(de_ctx);
3517     }
3518     FlowShutdown();
3519 
3520     return result;
3521 }
3522 
3523 /** \test Ensure that we set a bidirectional Signature correctly
3524 *         and we install it with the rest of the signatures, checking
3525 *         also that it match with the correct addr directions
3526 */
SigTestBidirec04(void)3527 static int SigTestBidirec04 (void)
3528 {
3529     int result = 0;
3530     Signature *sig = NULL;
3531     Packet *p = NULL;
3532 
3533     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3534     if (de_ctx == NULL)
3535         goto end;
3536 
3537     de_ctx->flags |= DE_QUIET;
3538 
3539     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)");
3540     if (sig == NULL)
3541         goto end;
3542     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)");
3543     if (sig == NULL)
3544         goto end;
3545     if ( !(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3546         goto end;
3547     if (sig->next == NULL)
3548         goto end;
3549     if (sig->next->next == NULL)
3550         goto end;
3551     if (sig->next->next->next != NULL)
3552         goto end;
3553     if (de_ctx->signum != 3)
3554         goto end;
3555 
3556     sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)");
3557     if (sig == NULL)
3558         goto end;
3559     if (sig->next == NULL)
3560         goto end;
3561     if (sig->next->next == NULL)
3562         goto end;
3563     if (sig->next->next->next == NULL)
3564         goto end;
3565     if (sig->next->next->next->next != NULL)
3566         goto end;
3567     if (de_ctx->signum != 4)
3568         goto end;
3569 
3570     uint8_t rawpkt1_ether[] = {
3571         0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3572         0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3573         0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3574         0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3575         0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3576         0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3577         0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3578         0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3579         0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3580         0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3581         0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3582         0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3583         0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3584         0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3585         0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3586         0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3587         0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3588         0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3589         0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3590         0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3591         0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3592         0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3593         0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3594         0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3595         0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3596         0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3597         0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3598         0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3599         0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3600         0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3601         0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3602         0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3603         0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3604         0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3605         0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3606         0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3607         0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3608         0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3609         0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3610         0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3611         0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3612         0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3613         0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3614         0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3615         0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3616         0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3617         0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3618         0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3619         0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3620         0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3621         0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3622         0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3623         0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3624         0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3625         0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3626 
3627     p = SCMalloc(SIZE_OF_PACKET);
3628     if (unlikely(p == NULL))
3629         return 0;
3630     DecodeThreadVars dtv;
3631     ThreadVars th_v;
3632     DetectEngineThreadCtx *det_ctx;
3633 
3634     memset(&th_v, 0, sizeof(th_v));
3635     memset(p, 0, SIZE_OF_PACKET);
3636 
3637     FlowInitConfig(FLOW_QUIET);
3638     DecodeEthernet(&th_v, &dtv, p, rawpkt1_ether, sizeof(rawpkt1_ether));
3639     DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3640 
3641     /* At this point we have a list of 4 signatures. The last one
3642        is a copy of the second one. If we receive a packet
3643        with source 192.168.1.1 80, all the sids should match */
3644 
3645     SigGroupBuild(de_ctx);
3646     SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3647 
3648     /* only sid 2 should match with a packet going to 192.168.1.1 port 80 */
3649     if (PacketAlertCheck(p, 1) <= 0 && PacketAlertCheck(p, 3) <= 0 &&
3650         PacketAlertCheck(p, 2) == 1) {
3651         result = 1;
3652     }
3653 
3654     if (p != NULL) {
3655         PACKET_RECYCLE(p);
3656     }
3657     FlowShutdown();
3658     DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
3659 
3660 end:
3661     if (de_ctx != NULL) {
3662         SigCleanSignatures(de_ctx);
3663         SigGroupCleanup(de_ctx);
3664         DetectEngineCtxFree(de_ctx);
3665     }
3666 
3667     if (p != NULL)
3668         SCFree(p);
3669     return result;
3670 }
3671 
3672 /**
3673  * \test check that we don't allow invalid negation options
3674  */
SigParseTestNegation01(void)3675 static int SigParseTestNegation01 (void)
3676 {
3677     int result = 0;
3678     DetectEngineCtx *de_ctx;
3679     Signature *s=NULL;
3680 
3681     de_ctx = DetectEngineCtxInit();
3682     if (de_ctx == NULL)
3683         goto end;
3684     de_ctx->flags |= DE_QUIET;
3685 
3686     s = SigInit(de_ctx,"alert tcp !any any -> any any (msg:\"SigTest41-01 src address is !any \"; classtype:misc-activity; sid:410001; rev:1;)");
3687     if (s != NULL) {
3688         SigFree(de_ctx, s);
3689         goto end;
3690     }
3691 
3692     result = 1;
3693 end:
3694     if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3695     return result;
3696 }
3697 
3698 /**
3699  * \test check that we don't allow invalid negation options
3700  */
SigParseTestNegation02(void)3701 static int SigParseTestNegation02 (void)
3702 {
3703     int result = 0;
3704     DetectEngineCtx *de_ctx;
3705     Signature *s=NULL;
3706 
3707     de_ctx = DetectEngineCtxInit();
3708     if (de_ctx == NULL)
3709         goto end;
3710     de_ctx->flags |= DE_QUIET;
3711 
3712     s = SigInit(de_ctx,"alert tcp any !any -> any any (msg:\"SigTest41-02 src ip is !any \"; classtype:misc-activity; sid:410002; rev:1;)");
3713     if (s != NULL) {
3714         SigFree(de_ctx, s);
3715         goto end;
3716     }
3717 
3718     result = 1;
3719 end:
3720     if (de_ctx != NULL)
3721         DetectEngineCtxFree(de_ctx);
3722     return result;
3723 }
3724 /**
3725  * \test check that we don't allow invalid negation options
3726  */
SigParseTestNegation03(void)3727 static int SigParseTestNegation03 (void)
3728 {
3729     int result = 0;
3730     DetectEngineCtx *de_ctx;
3731     Signature *s=NULL;
3732 
3733     de_ctx = DetectEngineCtxInit();
3734     if (de_ctx == NULL)
3735         goto end;
3736     de_ctx->flags |= DE_QUIET;
3737 
3738     s = SigInit(de_ctx,"alert tcp any any -> any [80:!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
3739     if (s != NULL) {
3740         SigFree(de_ctx, s);
3741         goto end;
3742     }
3743 
3744     result = 1;
3745 end:
3746     if (de_ctx != NULL)
3747         DetectEngineCtxFree(de_ctx);
3748     return result;
3749 }
3750 /**
3751  * \test check that we don't allow invalid negation options
3752  */
SigParseTestNegation04(void)3753 static int SigParseTestNegation04 (void)
3754 {
3755     int result = 0;
3756     DetectEngineCtx *de_ctx;
3757     Signature *s=NULL;
3758 
3759     de_ctx = DetectEngineCtxInit();
3760     if (de_ctx == NULL)
3761         goto end;
3762     de_ctx->flags |= DE_QUIET;
3763 
3764     s = SigInit(de_ctx,"alert tcp any any -> any [80,!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
3765     if (s != NULL) {
3766         SigFree(de_ctx, s);
3767         goto end;
3768     }
3769 
3770     result = 1;
3771 end:
3772     if (de_ctx != NULL)
3773         DetectEngineCtxFree(de_ctx);
3774     return result;
3775 }
3776 /**
3777  * \test check that we don't allow invalid negation options
3778  */
SigParseTestNegation05(void)3779 static int SigParseTestNegation05 (void)
3780 {
3781     int result = 0;
3782     DetectEngineCtx *de_ctx;
3783     Signature *s=NULL;
3784 
3785     de_ctx = DetectEngineCtxInit();
3786     if (de_ctx == NULL)
3787         goto end;
3788     de_ctx->flags |= DE_QUIET;
3789 
3790     s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.2,!192.168.0.2] any (msg:\"SigTest41-04 dst ip [192.168.0.2,!192.168.0.2] \"; classtype:misc-activity; sid:410004; rev:1;)");
3791     if (s != NULL) {
3792         SigFree(de_ctx, s);
3793         goto end;
3794     }
3795 
3796     result = 1;
3797 end:
3798     if (de_ctx != NULL)
3799         DetectEngineCtxFree(de_ctx);
3800     return result;
3801 }
3802 /**
3803  * \test check that we don't allow invalid negation options
3804  */
SigParseTestNegation06(void)3805 static int SigParseTestNegation06 (void)
3806 {
3807     int result = 0;
3808     DetectEngineCtx *de_ctx;
3809     Signature *s=NULL;
3810 
3811     de_ctx = DetectEngineCtxInit();
3812     if (de_ctx == NULL)
3813         goto end;
3814     de_ctx->flags |= DE_QUIET;
3815 
3816     s = SigInit(de_ctx,"alert tcp any any -> any [100:1000,!1:20000] (msg:\"SigTest41-05 dst port [100:1000,!1:20000] \"; classtype:misc-activity; sid:410005; rev:1;)");
3817     if (s != NULL) {
3818         SigFree(de_ctx, s);
3819         goto end;
3820     }
3821 
3822     result = 1;
3823 end:
3824     if (de_ctx != NULL)
3825         DetectEngineCtxFree(de_ctx);
3826     return result;
3827 }
3828 
3829 /**
3830  * \test check that we don't allow invalid negation options
3831  */
SigParseTestNegation07(void)3832 static int SigParseTestNegation07 (void)
3833 {
3834     int result = 0;
3835     DetectEngineCtx *de_ctx;
3836     Signature *s=NULL;
3837 
3838     de_ctx = DetectEngineCtxInit();
3839     if (de_ctx == NULL)
3840         goto end;
3841     de_ctx->flags |= DE_QUIET;
3842 
3843     s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.2,!192.168.0.0/24] any (msg:\"SigTest41-06 dst ip [192.168.0.2,!192.168.0.0/24] \"; classtype:misc-activity; sid:410006; rev:1;)");
3844     if (s != NULL) {
3845         SigFree(de_ctx, s);
3846         goto end;
3847     }
3848 
3849     result = 1;
3850 end:
3851     if (de_ctx != NULL)
3852         DetectEngineCtxFree(de_ctx);
3853     return result;
3854 }
3855 
3856 /**
3857  * \test check valid negation bug 1079
3858  */
SigParseTestNegation08(void)3859 static int SigParseTestNegation08 (void)
3860 {
3861     int result = 0;
3862     DetectEngineCtx *de_ctx;
3863     Signature *s=NULL;
3864 
3865     de_ctx = DetectEngineCtxInit();
3866     if (de_ctx == NULL)
3867         goto end;
3868     de_ctx->flags |= DE_QUIET;
3869 
3870     s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.0/16,!192.168.0.0/24] any (sid:410006; rev:1;)");
3871     if (s == NULL) {
3872         goto end;
3873     }
3874 
3875     result = 1;
3876 end:
3877     if (de_ctx != NULL)
3878         DetectEngineCtxFree(de_ctx);
3879     return result;
3880 }
3881 
3882 /**
3883  * \test mpm
3884  */
SigParseTestMpm01(void)3885 static int SigParseTestMpm01 (void)
3886 {
3887     int result = 0;
3888     Signature *sig = NULL;
3889 
3890     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3891     if (de_ctx == NULL)
3892         goto end;
3893 
3894     sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; sid:1;)");
3895     if (sig == NULL) {
3896         printf("sig failed to init: ");
3897         goto end;
3898     }
3899 
3900     if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
3901         printf("sig doesn't have content list: ");
3902         goto end;
3903     }
3904 
3905     result = 1;
3906 end:
3907     if (sig != NULL)
3908         SigFree(de_ctx, sig);
3909     DetectEngineCtxFree(de_ctx);
3910     return result;
3911 }
3912 
3913 /**
3914  * \test mpm
3915  */
SigParseTestMpm02(void)3916 static int SigParseTestMpm02 (void)
3917 {
3918     int result = 0;
3919     Signature *sig = NULL;
3920 
3921     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3922     if (de_ctx == NULL)
3923         goto end;
3924 
3925     sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; content:\"abcdef\"; sid:1;)");
3926     if (sig == NULL) {
3927         printf("sig failed to init: ");
3928         goto end;
3929     }
3930 
3931     if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
3932         printf("sig doesn't have content list: ");
3933         goto end;
3934     }
3935 
3936     result = 1;
3937 end:
3938     if (sig != NULL)
3939         SigFree(de_ctx, sig);
3940     DetectEngineCtxFree(de_ctx);
3941     return result;
3942 }
3943 
3944 /**
3945  * \test test tls (app layer) rule
3946  */
SigParseTestAppLayerTLS01(void)3947 static int SigParseTestAppLayerTLS01(void)
3948 {
3949     int result = 0;
3950     DetectEngineCtx *de_ctx;
3951     Signature *s=NULL;
3952 
3953     de_ctx = DetectEngineCtxInit();
3954     if (de_ctx == NULL)
3955         goto end;
3956     de_ctx->flags |= DE_QUIET;
3957 
3958     s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; sid:410006; rev:1;)");
3959     if (s == NULL) {
3960         printf("parsing sig failed: ");
3961         goto end;
3962     }
3963 
3964     if (s->alproto == 0) {
3965         printf("alproto not set: ");
3966         goto end;
3967     }
3968 
3969     result = 1;
3970 end:
3971     if (s != NULL)
3972         SigFree(de_ctx, s);
3973     if (de_ctx != NULL)
3974         DetectEngineCtxFree(de_ctx);
3975 
3976     return result;
3977 }
3978 
3979 /**
3980  * \test test tls (app layer) rule
3981  */
SigParseTestAppLayerTLS02(void)3982 static int SigParseTestAppLayerTLS02(void)
3983 {
3984     int result = 0;
3985     DetectEngineCtx *de_ctx;
3986     Signature *s=NULL;
3987 
3988     de_ctx = DetectEngineCtxInit();
3989     if (de_ctx == NULL)
3990         goto end;
3991     de_ctx->flags |= DE_QUIET;
3992 
3993     s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; sid:410006; rev:1;)");
3994     if (s == NULL) {
3995         printf("parsing sig failed: ");
3996         goto end;
3997     }
3998 
3999     if (s->alproto == 0) {
4000         printf("alproto not set: ");
4001         goto end;
4002     }
4003 
4004     result = 1;
4005 end:
4006     if (s != NULL)
4007         SigFree(de_ctx, s);
4008     if (de_ctx != NULL)
4009         DetectEngineCtxFree(de_ctx);
4010     return result;
4011 }
4012 
4013 /**
4014  * \test test tls (app layer) rule
4015  */
SigParseTestAppLayerTLS03(void)4016 static int SigParseTestAppLayerTLS03(void)
4017 {
4018     int result = 0;
4019     DetectEngineCtx *de_ctx;
4020     Signature *s=NULL;
4021 
4022     de_ctx = DetectEngineCtxInit();
4023     if (de_ctx == NULL)
4024         goto end;
4025     de_ctx->flags |= DE_QUIET;
4026 
4027     s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; tls.version:2.5; sid:410006; rev:1;)");
4028     if (s != NULL) {
4029         SigFree(de_ctx, s);
4030         goto end;
4031     }
4032 
4033     result = 1;
4034 end:
4035     if (de_ctx != NULL)
4036         DetectEngineCtxFree(de_ctx);
4037     return result;
4038 }
4039 
SigParseTestUnblanacedQuotes01(void)4040 static int SigParseTestUnblanacedQuotes01(void)
4041 {
4042     DetectEngineCtx *de_ctx;
4043     Signature *s;
4044 
4045     de_ctx = DetectEngineCtxInit();
4046     FAIL_IF_NULL(de_ctx);
4047     de_ctx->flags |= DE_QUIET;
4048 
4049     s = SigInit(de_ctx, "alert http any any -> any any (msg:\"SigParseTestUnblanacedQuotes01\"; pcre:\"/\\/[a-z]+\\.php\\?[a-z]+?=\\d{7}&[a-z]+?=\\d{7,8}$/U\" flowbits:set,et.exploitkitlanding; classtype:trojan-activity; sid:2017078; rev:5;)");
4050     FAIL_IF_NOT_NULL(s);
4051 
4052     PASS;
4053 }
4054 
SigParseTestContentGtDsize01(void)4055 static int SigParseTestContentGtDsize01(void)
4056 {
4057     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4058     FAIL_IF_NULL(de_ctx);
4059     de_ctx->flags |= DE_QUIET;
4060 
4061     Signature *s = SigInit(de_ctx,
4062             "alert http any any -> any any ("
4063             "dsize:21; content:\"0123456789001234567890|00 00|\"; "
4064             "sid:1; rev:1;)");
4065     FAIL_IF_NOT_NULL(s);
4066 
4067     PASS;
4068 }
4069 
SigParseTestContentGtDsize02(void)4070 static int SigParseTestContentGtDsize02(void)
4071 {
4072     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4073     FAIL_IF_NULL(de_ctx);
4074     de_ctx->flags |= DE_QUIET;
4075 
4076     Signature *s = SigInit(de_ctx,
4077             "alert http any any -> any any ("
4078             "dsize:21; content:\"0123456789|00 00|\"; offset:10; "
4079             "sid:1; rev:1;)");
4080     FAIL_IF_NOT_NULL(s);
4081 
4082     PASS;
4083 }
4084 
SigParseBidirWithSameSrcAndDest01(void)4085 static int SigParseBidirWithSameSrcAndDest01(void)
4086 {
4087     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4088     FAIL_IF_NULL(de_ctx);
4089     de_ctx->flags |= DE_QUIET;
4090 
4091     Signature *s = SigInit(de_ctx,
4092             "alert tcp any any <> any any (sid:1; rev:1;)");
4093     FAIL_IF_NULL(s);
4094     FAIL_IF_NOT_NULL(s->next);
4095     FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4096 
4097     SigFree(de_ctx, s);
4098 
4099     s = SigInit(de_ctx,
4100             "alert tcp any [80, 81] <> any [81, 80] (sid:1; rev:1;)");
4101     FAIL_IF_NULL(s);
4102     FAIL_IF_NOT_NULL(s->next);
4103     FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4104 
4105     SigFree(de_ctx, s);
4106 
4107     s = SigInit(de_ctx,
4108             "alert tcp [1.2.3.4, 5.6.7.8] [80, 81] <> [5.6.7.8, 1.2.3.4] [81, 80] (sid:1; rev:1;)");
4109     FAIL_IF_NULL(s);
4110     FAIL_IF_NOT_NULL(s->next);
4111     FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4112 
4113     SigFree(de_ctx, s);
4114 
4115     PASS;
4116 }
4117 
SigParseBidirWithSameSrcAndDest02(void)4118 static int SigParseBidirWithSameSrcAndDest02(void)
4119 {
4120     DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4121     FAIL_IF_NULL(de_ctx);
4122     de_ctx->flags |= DE_QUIET;
4123 
4124     // Source is a subset of destination
4125     Signature *s = SigInit(de_ctx,
4126             "alert tcp 1.2.3.4 any <> [1.2.3.4, 5.6.7.8, ::1] any (sid:1; rev:1;)");
4127     FAIL_IF_NULL(s);
4128     FAIL_IF_NULL(s->next);
4129     FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4130 
4131     SigFree(de_ctx, s);
4132 
4133     // Source is a subset of destination
4134     s = SigInit(de_ctx,
4135             "alert tcp [1.2.3.4, ::1] [80, 81, 82] <> [1.2.3.4, ::1] [80, 81] (sid:1; rev:1;)");
4136     FAIL_IF_NULL(s);
4137     FAIL_IF_NULL(s->next);
4138     FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4139 
4140     SigFree(de_ctx, s);
4141 
4142     // Source intersects with destination
4143     s = SigInit(de_ctx,
4144             "alert tcp [1.2.3.4, ::1, ABCD:AAAA::1] [80] <> [1.2.3.4, ::1] [80, 81] (sid:1; rev:1;)");
4145     FAIL_IF_NULL(s);
4146     FAIL_IF_NULL(s->next);
4147     FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4148 
4149     SigFree(de_ctx, s);
4150 
4151     PASS;
4152 }
4153 
4154 #endif /* UNITTESTS */
4155 
4156 #ifdef UNITTESTS
4157 void DetectParseRegisterTests (void);
4158 #include "tests/detect-parse.c"
4159 #endif
4160 
SigParseRegisterTests(void)4161 void SigParseRegisterTests(void)
4162 {
4163 #ifdef UNITTESTS
4164     DetectParseRegisterTests();
4165 
4166     UtRegisterTest("SigParseTest01", SigParseTest01);
4167     UtRegisterTest("SigParseTest02", SigParseTest02);
4168     UtRegisterTest("SigParseTest03", SigParseTest03);
4169     UtRegisterTest("SigParseTest04", SigParseTest04);
4170     UtRegisterTest("SigParseTest05", SigParseTest05);
4171     UtRegisterTest("SigParseTest06", SigParseTest06);
4172     UtRegisterTest("SigParseTest07", SigParseTest07);
4173     UtRegisterTest("SigParseTest08", SigParseTest08);
4174     UtRegisterTest("SigParseTest09", SigParseTest09);
4175     UtRegisterTest("SigParseTest10", SigParseTest10);
4176     UtRegisterTest("SigParseTest11", SigParseTest11);
4177     UtRegisterTest("SigParseTest12", SigParseTest12);
4178     UtRegisterTest("SigParseTest13", SigParseTest13);
4179     UtRegisterTest("SigParseTest14", SigParseTest14);
4180     UtRegisterTest("SigParseTest15", SigParseTest15);
4181     UtRegisterTest("SigParseTest16", SigParseTest16);
4182     UtRegisterTest("SigParseTest17", SigParseTest17);
4183     UtRegisterTest("SigParseTest18", SigParseTest18);
4184     UtRegisterTest("SigParseTest19", SigParseTest19);
4185     UtRegisterTest("SigParseTest20", SigParseTest20);
4186     UtRegisterTest("SigParseTest21 -- address with space", SigParseTest21);
4187     UtRegisterTest("SigParseTest22 -- address with space", SigParseTest22);
4188     UtRegisterTest("SigParseTest23 -- carriage return", SigParseTest23);
4189 
4190     UtRegisterTest("SigParseBidirecTest06", SigParseBidirecTest06);
4191     UtRegisterTest("SigParseBidirecTest07", SigParseBidirecTest07);
4192     UtRegisterTest("SigParseBidirecTest08", SigParseBidirecTest08);
4193     UtRegisterTest("SigParseBidirecTest09", SigParseBidirecTest09);
4194     UtRegisterTest("SigParseBidirecTest10", SigParseBidirecTest10);
4195     UtRegisterTest("SigParseBidirecTest11", SigParseBidirecTest11);
4196     UtRegisterTest("SigParseBidirecTest12", SigParseBidirecTest12);
4197     UtRegisterTest("SigParseBidirecTest13", SigParseBidirecTest13);
4198     UtRegisterTest("SigParseBidirecTest14", SigParseBidirecTest14);
4199     UtRegisterTest("SigTestBidirec01", SigTestBidirec01);
4200     UtRegisterTest("SigTestBidirec02", SigTestBidirec02);
4201     UtRegisterTest("SigTestBidirec03", SigTestBidirec03);
4202     UtRegisterTest("SigTestBidirec04", SigTestBidirec04);
4203     UtRegisterTest("SigParseTestNegation01", SigParseTestNegation01);
4204     UtRegisterTest("SigParseTestNegation02", SigParseTestNegation02);
4205     UtRegisterTest("SigParseTestNegation03", SigParseTestNegation03);
4206     UtRegisterTest("SigParseTestNegation04", SigParseTestNegation04);
4207     UtRegisterTest("SigParseTestNegation05", SigParseTestNegation05);
4208     UtRegisterTest("SigParseTestNegation06", SigParseTestNegation06);
4209     UtRegisterTest("SigParseTestNegation07", SigParseTestNegation07);
4210     UtRegisterTest("SigParseTestNegation08", SigParseTestNegation08);
4211     UtRegisterTest("SigParseTestMpm01", SigParseTestMpm01);
4212     UtRegisterTest("SigParseTestMpm02", SigParseTestMpm02);
4213     UtRegisterTest("SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01);
4214     UtRegisterTest("SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02);
4215     UtRegisterTest("SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03);
4216     UtRegisterTest("SigParseTestUnblanacedQuotes01",
4217         SigParseTestUnblanacedQuotes01);
4218 
4219     UtRegisterTest("SigParseTestContentGtDsize01",
4220             SigParseTestContentGtDsize01);
4221     UtRegisterTest("SigParseTestContentGtDsize02",
4222             SigParseTestContentGtDsize02);
4223 
4224     UtRegisterTest("SigParseBidirWithSameSrcAndDest01",
4225             SigParseBidirWithSameSrcAndDest01);
4226     UtRegisterTest("SigParseBidirWithSameSrcAndDest02",
4227             SigParseBidirWithSameSrcAndDest02);
4228 #endif /* UNITTESTS */
4229 }
4230