Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/src/detect-flowint.c
Line
Count
Source
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 Pablo Rincon <pablo.rincon.crespo@gmail.com>
22
 *
23
 * Flowvar management for integer types, part of the detection engine
24
 * Keyword: flowint
25
 */
26
27
#include "suricata-common.h"
28
#include "decode.h"
29
#include "detect.h"
30
#include "threads.h"
31
#include "flow.h"
32
#include "flow-var.h"
33
#include "detect-flowint.h"
34
#include "util-spm.h"
35
#include "util-var-name.h"
36
#include "util-debug.h"
37
#include "util-unittest.h"
38
#include "util-unittest-helper.h"
39
40
#include "detect-parse.h"
41
#include "detect-engine.h"
42
#include "detect-engine-mpm.h"
43
#include "detect-engine-sigorder.h"
44
#include "detect-engine-build.h"
45
46
#include "pkt-var.h"
47
#include "host.h"
48
#include "util-profiling.h"
49
50
/*                         name             modifiers          value      */
51
#define PARSE_REGEX                                                                                \
52
79
    "^\\s*([a-zA-Z][\\w\\d_./"                                                                     \
53
79
    "]+)\\s*,\\s*([+=-]{1}|==|!=|<|<=|>|>=|isset|notset|isnotset)\\s*,?\\s*([a-zA-Z][\\w\\d]+|["   \
54
79
    "\\d]{1,10})?\\s*$"
55
/* Varnames must begin with a letter */
56
57
static DetectParseRegex parse_regex;
58
59
int DetectFlowintMatch(DetectEngineThreadCtx *, Packet *,
60
                       const Signature *, const SigMatchCtx *);
61
static int DetectFlowintSetup(DetectEngineCtx *, Signature *, const char *);
62
void DetectFlowintFree(DetectEngineCtx *, void *);
63
#ifdef UNITTESTS
64
static void DetectFlowintRegisterTests(void);
65
#endif
66
67
void DetectFlowintRegister(void)
68
79
{
69
79
    sigmatch_table[DETECT_FLOWINT].name = "flowint";
70
79
    sigmatch_table[DETECT_FLOWINT].desc = "operate on a per-flow integer";
71
79
    sigmatch_table[DETECT_FLOWINT].url = "/rules/flow-keywords.html#flowint";
72
79
    sigmatch_table[DETECT_FLOWINT].Match = DetectFlowintMatch;
73
79
    sigmatch_table[DETECT_FLOWINT].Setup = DetectFlowintSetup;
74
79
    sigmatch_table[DETECT_FLOWINT].Free = DetectFlowintFree;
75
#ifdef UNITTESTS
76
    sigmatch_table[DETECT_FLOWINT].RegisterTests = DetectFlowintRegisterTests;
77
#endif
78
79
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
79
79
}
80
81
/**
82
 * \brief This function is used to create a flowint, add/substract values,
83
 *        compare it with other flowints, etc
84
 *
85
 * \param t pointer to thread vars
86
 * \param det_ctx pointer to the pattern matcher thread
87
 * \param p pointer to the current packet
88
 * \param s  pointer to the current Signature
89
 * \param m pointer to the sigmatch that we will cast into DetectFlowintData
90
 *
91
 * \retval 0 no match, when a var doesn't exist
92
 * \retval 1 match, when a var is initialized well, add/subtracted, or a true
93
 * condition
94
 */
95
int DetectFlowintMatch(DetectEngineThreadCtx *det_ctx,
96
                        Packet *p, const Signature *s, const SigMatchCtx *ctx)
97
4.89k
{
98
4.89k
    const DetectFlowintData *sfd = (const DetectFlowintData *)ctx;
99
4.89k
    FlowVar *fv;
100
4.89k
    FlowVar *fvt;
101
4.89k
    uint32_t targetval;
102
4.89k
    int ret = 0;
103
104
4.89k
    if (p->flow == NULL)
105
643
        return 0;
106
107
    /** ATM If we are going to compare the current var with another
108
     * that doesn't exist, the default value will be zero;
109
     * if you don't want this behaviour, you can use the keyword
110
     * "isset" to make it match or not before using the default
111
     * value of zero;
112
     * But it is mandatory that the current var exist, otherwise, it will
113
     * return zero(not match).
114
     */
115
4.25k
    if (sfd->targettype == FLOWINT_TARGET_VAR) {
116
320
        uint32_t tvar_idx = VarNameStoreLookupByName(sfd->target.tvar.name, VAR_TYPE_FLOW_INT);
117
118
320
        fvt = FlowVarGet(p->flow, tvar_idx);
119
            /* We don't have that variable initialized yet */
120
320
        if (fvt == NULL)
121
320
            targetval = 0;
122
0
        else
123
0
            targetval = fvt->data.fv_int.value;
124
3.93k
    } else {
125
3.93k
        targetval = sfd->target.value;
126
3.93k
    }
127
128
4.25k
    SCLogDebug("Our var %s is at idx: %"PRIu32"", sfd->name, sfd->idx);
129
130
4.25k
    if (sfd->modifier == FLOWINT_MODIFIER_SET) {
131
0
        FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
132
0
        SCLogDebug("Setting %s = %u", sfd->name, targetval);
133
0
        ret = 1;
134
0
        goto end;
135
0
    }
136
137
4.25k
    fv = FlowVarGet(p->flow, sfd->idx);
138
139
4.25k
    if (sfd->modifier == FLOWINT_MODIFIER_ISSET) {
140
0
        SCLogDebug(" Isset %s? = %u", sfd->name,(fv) ? 1 : 0);
141
0
        if (fv != NULL)
142
0
            ret = 1;
143
0
        goto end;
144
0
    }
145
146
4.25k
    if (sfd->modifier == FLOWINT_MODIFIER_ISNOTSET) {
147
0
        SCLogDebug(" Not set %s? = %u", sfd->name,(fv) ? 0 : 1);
148
0
        if (fv == NULL)
149
0
            ret = 1;
150
0
        goto end;
151
0
    }
152
153
4.25k
    if (fv != NULL && fv->datatype == FLOWVAR_TYPE_INT) {
154
2.35k
        if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
155
2.17k
            SCLogDebug("Adding %u to %s", targetval, sfd->name);
156
2.17k
            FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value +
157
2.17k
                           targetval);
158
2.17k
            ret = 1;
159
2.17k
            goto end;
160
2.17k
        }
161
162
177
        if (sfd->modifier == FLOWINT_MODIFIER_SUB) {
163
0
            SCLogDebug("Subtracting %u to %s", targetval, sfd->name);
164
0
            FlowVarAddIntNoLock(p->flow, sfd->idx, fv->data.fv_int.value -
165
0
                           targetval);
166
0
            ret = 1;
167
0
            goto end;
168
0
        }
169
170
177
        switch(sfd->modifier) {
171
0
            case FLOWINT_MODIFIER_EQ:
172
0
                SCLogDebug("( %u EQ %u )", fv->data.fv_int.value, targetval);
173
0
                ret = (fv->data.fv_int.value == targetval);
174
0
                break;
175
0
            case FLOWINT_MODIFIER_NE:
176
0
                SCLogDebug("( %u NE %u )", fv->data.fv_int.value, targetval);
177
0
                ret = (fv->data.fv_int.value != targetval);
178
0
                break;
179
1
            case FLOWINT_MODIFIER_LT:
180
1
                SCLogDebug("( %u LT %u )", fv->data.fv_int.value, targetval);
181
1
                ret = (fv->data.fv_int.value < targetval);
182
1
                break;
183
0
            case FLOWINT_MODIFIER_LE:
184
0
                SCLogDebug("( %u LE %u )", fv->data.fv_int.value, targetval);
185
0
                ret = (fv->data.fv_int.value <= targetval);
186
0
                break;
187
0
            case FLOWINT_MODIFIER_GT:
188
0
                SCLogDebug("( %u GT %u )", fv->data.fv_int.value, targetval);
189
0
                ret = (fv->data.fv_int.value > targetval);
190
0
                break;
191
176
            case FLOWINT_MODIFIER_GE:
192
176
                SCLogDebug("( %u GE %u )", fv->data.fv_int.value, targetval);
193
176
                ret = (fv->data.fv_int.value >= targetval);
194
176
                break;
195
0
            default:
196
0
                SCLogDebug("Unknown Modifier!");
197
#ifdef DEBUG
198
                BUG_ON(1);
199
#endif
200
177
        }
201
1.90k
    } else {
202
        /* allow a add on a non-existing var, it will init to the "add" value,
203
         * so implying a 0 set. */
204
1.90k
        if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
205
397
            SCLogDebug("Adding %u to %s (new var)", targetval, sfd->name);
206
397
            FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
207
397
            ret = 1;
208
1.50k
        } else {
209
1.50k
            SCLogDebug("Var not found!");
210
            /* It doesn't exist because it wasn't set
211
             * or it is a string var, that we don't compare here
212
             */
213
1.50k
            ret = 0;
214
1.50k
        }
215
1.90k
    }
216
217
4.25k
end:
218
4.25k
    return ret;
219
4.25k
}
220
221
/**
222
 * \brief This function is used to parse a flowint option
223
 *
224
 * \param de_ctx pointer to the engine context
225
 * \param rawstr pointer to the string holding the options
226
 *
227
 * \retval NULL if invalid option
228
 * \retval DetectFlowintData pointer with the flowint parsed
229
 */
230
static DetectFlowintData *DetectFlowintParse(DetectEngineCtx *de_ctx, const char *rawstr)
231
17.4k
{
232
17.4k
    DetectFlowintData *sfd = NULL;
233
17.4k
    char *varname = NULL;
234
17.4k
    char *varval = NULL;
235
17.4k
    char *modstr = NULL;
236
17.4k
    int res = 0;
237
17.4k
    size_t pcre2_len;
238
17.4k
    uint8_t modifier = FLOWINT_MODIFIER_UNKNOWN;
239
17.4k
    unsigned long long value_long = 0;
240
17.4k
    const char *str_ptr;
241
17.4k
    pcre2_match_data *match = NULL;
242
243
17.4k
    int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
244
17.4k
    if (ret < 3 || ret > 4) {
245
260
        SCLogError("\"%s\" is not a valid setting for flowint(ret = %d).", rawstr, ret);
246
260
        goto error;
247
260
    }
248
249
    /* Get our flowint varname */
250
17.1k
    res = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
251
17.1k
    if (res < 0 || str_ptr == NULL) {
252
0
        SCLogError("pcre2_substring_get_bynumber failed");
253
0
        goto error;
254
0
    }
255
17.1k
    varname = (char *)str_ptr;
256
257
17.1k
    res = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
258
17.1k
    if (res < 0 || str_ptr == NULL) {
259
0
        SCLogError("pcre2_substring_get_bynumber failed");
260
0
        goto error;
261
0
    }
262
17.1k
    modstr = (char *)str_ptr;
263
264
    /* Get the modifier */
265
17.1k
    if (strcmp("=", modstr) == 0)
266
18
        modifier = FLOWINT_MODIFIER_SET;
267
17.1k
    if (strcmp("+", modstr) == 0)
268
10.4k
        modifier = FLOWINT_MODIFIER_ADD;
269
17.1k
    if (strcmp("-", modstr) == 0)
270
42
        modifier = FLOWINT_MODIFIER_SUB;
271
272
17.1k
    if (strcmp("<", modstr) == 0)
273
1.15k
        modifier = FLOWINT_MODIFIER_LT;
274
17.1k
    if (strcmp("<=", modstr) == 0)
275
242
        modifier = FLOWINT_MODIFIER_LE;
276
17.1k
    if (strcmp("!=", modstr) == 0)
277
1.68k
        modifier = FLOWINT_MODIFIER_NE;
278
17.1k
    if (strcmp("==", modstr) == 0)
279
10
        modifier = FLOWINT_MODIFIER_EQ;
280
17.1k
    if (strcmp(">=", modstr) == 0)
281
2.55k
        modifier = FLOWINT_MODIFIER_GE;
282
17.1k
    if (strcmp(">", modstr) == 0)
283
1.03k
        modifier = FLOWINT_MODIFIER_GT;
284
17.1k
    if (strcmp("isset", modstr) == 0)
285
0
        modifier = FLOWINT_MODIFIER_ISSET;
286
17.1k
    if (strcmp("notset", modstr) == 0 || strcmp("isnotset", modstr) == 0)
287
0
        modifier = FLOWINT_MODIFIER_ISNOTSET;
288
289
17.1k
    if (modifier == FLOWINT_MODIFIER_UNKNOWN) {
290
0
        SCLogError("Unknown modifier");
291
0
        goto error;
292
0
    }
293
294
17.1k
    sfd = SCMalloc(sizeof(DetectFlowintData));
295
17.1k
    if (unlikely(sfd == NULL))
296
0
        goto error;
297
298
    /* If we need another arg, check it out(isset doesn't need another arg) */
299
17.1k
    if (modifier != FLOWINT_MODIFIER_ISSET && modifier != FLOWINT_MODIFIER_ISNOTSET) {
300
17.1k
        if (ret < 4)
301
1
            goto error;
302
303
17.1k
        res = pcre2_substring_get_bynumber(match, 3, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
304
17.1k
        varval = (char *)str_ptr;
305
17.1k
        if (res < 0 || varval == NULL || strcmp(varval, "") == 0) {
306
0
            SCLogError("pcre2_substring_get_bynumber failed");
307
0
            goto error;
308
0
        }
309
310
17.1k
        if (varval[0] >= '0' && varval[0] <= '9') { /* is digit, look at the regexp */
311
15.2k
            sfd->targettype = FLOWINT_TARGET_VAL;
312
15.2k
            value_long = atoll(varval);
313
15.2k
            if (value_long > UINT32_MAX) {
314
1
                SCLogDebug("DetectFlowintParse: Cannot load this value."
315
1
                            " Values should be between 0 and %"PRIu32, UINT32_MAX);
316
1
                goto error;
317
1
            }
318
15.2k
            sfd->target.value = (uint32_t) value_long;
319
15.2k
        } else {
320
1.94k
            sfd->targettype = FLOWINT_TARGET_VAR;
321
1.94k
            sfd->target.tvar.name = SCStrdup(varval);
322
1.94k
            if (unlikely(sfd->target.tvar.name == NULL)) {
323
0
                SCLogError("malloc from strdup failed");
324
0
                goto error;
325
0
            }
326
1.94k
        }
327
17.1k
    } else {
328
0
        sfd->targettype = FLOWINT_TARGET_SELF;
329
0
    }
330
331
    /* Set the name of the origin var to modify/compared with the target */
332
17.1k
    sfd->name = SCStrdup(varname);
333
17.1k
    if (unlikely(sfd->name == NULL)) {
334
0
        SCLogError("malloc from strdup failed");
335
0
        goto error;
336
0
    }
337
17.1k
    sfd->idx = VarNameStoreRegister(varname, VAR_TYPE_FLOW_INT);
338
17.1k
    SCLogDebug("sfd->name %s id %u", sfd->name, sfd->idx);
339
17.1k
    sfd->modifier = modifier;
340
341
17.1k
    pcre2_substring_free((PCRE2_UCHAR *)varname);
342
17.1k
    pcre2_substring_free((PCRE2_UCHAR *)modstr);
343
17.1k
    if (varval)
344
17.1k
        pcre2_substring_free((PCRE2_UCHAR *)varval);
345
17.1k
    pcre2_match_data_free(match);
346
17.1k
    return sfd;
347
262
error:
348
262
    if (match) {
349
262
        pcre2_match_data_free(match);
350
262
    }
351
262
    if (varname)
352
262
        pcre2_substring_free((PCRE2_UCHAR *)varname);
353
262
    if (varval)
354
262
        pcre2_substring_free((PCRE2_UCHAR *)varval);
355
262
    if (modstr)
356
262
        pcre2_substring_free((PCRE2_UCHAR *)modstr);
357
262
    if (sfd != NULL)
358
2
        SCFree(sfd);
359
262
    return NULL;
360
17.1k
}
361
362
/**
363
 * \brief This function is used to set up the SigMatch holding the flowint opt
364
 *
365
 * \param de_ctx pointer to the engine context
366
 * \param s  pointer to the current Signature
367
 * \param rawstr pointer to the string holding the options
368
 *
369
 * \retval 0 if all is ok
370
 * \retval -1 if we find any problem
371
 */
372
static int DetectFlowintSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
373
17.4k
{
374
17.4k
    DetectFlowintData *sfd = NULL;
375
376
17.4k
    sfd = DetectFlowintParse(de_ctx, rawstr);
377
17.4k
    if (sfd == NULL)
378
262
        goto error;
379
380
    /* Okay so far so good, lets get this into a SigMatch
381
     * and put it in the Signature. */
382
383
17.1k
    switch (sfd->modifier) {
384
18
        case FLOWINT_MODIFIER_SET:
385
10.4k
        case FLOWINT_MODIFIER_ADD:
386
10.4k
        case FLOWINT_MODIFIER_SUB:
387
10.4k
            if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_FLOWINT, (SigMatchCtx *)sfd,
388
10.4k
                        DETECT_SM_LIST_POSTMATCH) == NULL) {
389
0
                goto error;
390
0
            }
391
10.4k
            break;
392
393
10.4k
        case FLOWINT_MODIFIER_LT:
394
1.39k
        case FLOWINT_MODIFIER_LE:
395
3.08k
        case FLOWINT_MODIFIER_NE:
396
3.09k
        case FLOWINT_MODIFIER_EQ:
397
5.65k
        case FLOWINT_MODIFIER_GE:
398
6.68k
        case FLOWINT_MODIFIER_GT:
399
6.68k
        case FLOWINT_MODIFIER_ISSET:
400
6.68k
        case FLOWINT_MODIFIER_ISNOTSET:
401
6.68k
            if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_FLOWINT, (SigMatchCtx *)sfd,
402
6.68k
                        DETECT_SM_LIST_MATCH) == NULL) {
403
0
                goto error;
404
0
            }
405
6.68k
            break;
406
6.68k
        default:
407
0
            goto error;
408
17.1k
    }
409
410
17.1k
    return 0;
411
412
262
error:
413
262
    if (sfd)
414
0
        DetectFlowintFree(de_ctx, sfd);
415
262
    return -1;
416
17.1k
}
417
418
/**
419
 * \brief This function is used to free the data of DetectFlowintData
420
 */
421
void DetectFlowintFree(DetectEngineCtx *de_ctx, void *tmp)
422
17.1k
{
423
17.1k
    DetectFlowintData *sfd =(DetectFlowintData*) tmp;
424
17.1k
    if (sfd != NULL) {
425
17.1k
        VarNameStoreUnregister(sfd->idx, VAR_TYPE_FLOW_INT);
426
17.1k
        if (sfd->name != NULL)
427
17.1k
            SCFree(sfd->name);
428
17.1k
        if (sfd->targettype == FLOWINT_TARGET_VAR)
429
1.94k
            if (sfd->target.tvar.name != NULL)
430
1.94k
                SCFree(sfd->target.tvar.name);
431
17.1k
        SCFree(sfd);
432
17.1k
    }
433
17.1k
}
434
435
#ifdef UNITTESTS
436
#include "detect-engine-alert.h"
437
/**
438
 * \brief This is a helper function used for debugging purposes
439
 */
440
static void DetectFlowintPrintData(DetectFlowintData *sfd)
441
{
442
    if (sfd == NULL) {
443
        SCLogDebug("DetectFlowintPrintData: Error, DetectFlowintData == NULL!");
444
        return;
445
    }
446
447
    SCLogDebug("Varname: %s, modifier: %"PRIu8", idx: %"PRIu32" Target: ",
448
                sfd->name, sfd->modifier, sfd->idx);
449
    switch(sfd->targettype) {
450
        case FLOWINT_TARGET_VAR:
451
            SCLogDebug("target_var: %s",
452
                        sfd->target.tvar.name);
453
            break;
454
        case FLOWINT_TARGET_VAL:
455
            SCLogDebug("Value: %"PRIu32"; ", sfd->target.value);
456
            break;
457
        default :
458
            SCLogDebug("DetectFlowintPrintData: Error, Targettype not known!");
459
    }
460
}
461
462
/**
463
 * \test DetectFlowintTestParseVal01 is a test to make sure that we set the
464
 *  DetectFlowint correctly for setting a valid target value
465
 */
466
static int DetectFlowintTestParseVal01(void)
467
{
468
    int result = 0;
469
    DetectFlowintData *sfd = NULL;
470
    DetectEngineCtx *de_ctx;
471
    de_ctx = DetectEngineCtxInit();
472
    if (de_ctx == NULL)
473
        return 0;
474
    de_ctx->flags |= DE_QUIET;
475
476
    sfd = DetectFlowintParse(de_ctx, "myvar,=,35");
477
    DetectFlowintPrintData(sfd);
478
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
479
            && sfd->modifier == FLOWINT_MODIFIER_SET) {
480
        result = 1;
481
    }
482
    if (sfd) DetectFlowintFree(NULL, sfd);
483
484
    DetectEngineCtxFree(de_ctx);
485
486
    return result;
487
}
488
489
/**
490
 * \test DetectFlowintTestParseVar01 is a test to make sure that we set the
491
 *  DetectFlowint correctly for setting a valid target variable
492
 */
493
static int DetectFlowintTestParseVar01(void)
494
{
495
    int result = 0;
496
    DetectFlowintData *sfd = NULL;
497
    DetectEngineCtx *de_ctx;
498
    de_ctx = DetectEngineCtxInit();
499
    if (de_ctx == NULL)
500
        return 0;
501
    de_ctx->flags |= DE_QUIET;
502
503
    sfd = DetectFlowintParse(de_ctx, "myvar,=,targetvar");
504
    DetectFlowintPrintData(sfd);
505
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
506
            && sfd->targettype == FLOWINT_TARGET_VAR
507
            && sfd->target.tvar.name != NULL
508
            && !strcmp(sfd->target.tvar.name, "targetvar")
509
            && sfd->modifier == FLOWINT_MODIFIER_SET) {
510
511
        result = 1;
512
    }
513
    if (sfd) DetectFlowintFree(NULL, sfd);
514
    DetectEngineCtxFree(de_ctx);
515
516
    return result;
517
}
518
519
/**
520
 * \test DetectFlowintTestParseVal02 is a test to make sure that we set the
521
 *  DetectFlowint correctly for adding a valid target value
522
 */
523
static int DetectFlowintTestParseVal02(void)
524
{
525
    int result = 0;
526
    DetectFlowintData *sfd = NULL;
527
    DetectEngineCtx *de_ctx;
528
    de_ctx = DetectEngineCtxInit();
529
    if (de_ctx == NULL)
530
        return 0;
531
    de_ctx->flags |= DE_QUIET;
532
533
    sfd = DetectFlowintParse(de_ctx, "myvar,+,35");
534
    DetectFlowintPrintData(sfd);
535
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
536
            && sfd->modifier == FLOWINT_MODIFIER_ADD) {
537
        result = 1;
538
    }
539
    if (sfd) DetectFlowintFree(NULL, sfd);
540
541
    DetectEngineCtxFree(de_ctx);
542
543
    return result;
544
}
545
546
/**
547
 * \test DetectFlowintTestParseVar02 is a test to make sure that we set the
548
 *  DetectFlowint correctly for adding a valid target variable
549
 */
550
static int DetectFlowintTestParseVar02(void)
551
{
552
    int result = 0;
553
    DetectFlowintData *sfd = NULL;
554
    DetectEngineCtx *de_ctx;
555
    de_ctx = DetectEngineCtxInit();
556
    if (de_ctx == NULL)
557
        return 0;
558
    de_ctx->flags |= DE_QUIET;
559
560
    sfd = DetectFlowintParse(de_ctx, "myvar,+,targetvar");
561
    DetectFlowintPrintData(sfd);
562
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
563
            && sfd->targettype == FLOWINT_TARGET_VAR
564
            && sfd->target.tvar.name != NULL
565
            && !strcmp(sfd->target.tvar.name, "targetvar")
566
            && sfd->modifier == FLOWINT_MODIFIER_ADD) {
567
568
        result = 1;
569
    }
570
    if (sfd) DetectFlowintFree(NULL, sfd);
571
    DetectEngineCtxFree(de_ctx);
572
573
    return result;
574
}
575
576
/**
577
 * \test DetectFlowintTestParseVal03 is a test to make sure that we set the
578
 *  DetectFlowint correctly for substract a valid target value
579
 */
580
static int DetectFlowintTestParseVal03(void)
581
{
582
    int result = 0;
583
    DetectFlowintData *sfd = NULL;
584
    DetectEngineCtx *de_ctx;
585
    de_ctx = DetectEngineCtxInit();
586
    if (de_ctx == NULL)
587
        return 0;
588
    de_ctx->flags |= DE_QUIET;
589
590
    sfd = DetectFlowintParse(de_ctx, "myvar,-,35");
591
    DetectFlowintPrintData(sfd);
592
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
593
            && sfd->modifier == FLOWINT_MODIFIER_SUB) {
594
        result = 1;
595
    }
596
    if (sfd) DetectFlowintFree(NULL, sfd);
597
598
    DetectEngineCtxFree(de_ctx);
599
600
    return result;
601
}
602
603
/**
604
 * \test DetectFlowintTestParseVar03 is a test to make sure that we set the
605
 *  DetectFlowint correctly for substract a valid target variable
606
 */
607
static int DetectFlowintTestParseVar03(void)
608
{
609
    int result = 0;
610
    DetectFlowintData *sfd = NULL;
611
    DetectEngineCtx *de_ctx;
612
    de_ctx = DetectEngineCtxInit();
613
    if (de_ctx == NULL)
614
        return 0;
615
    de_ctx->flags |= DE_QUIET;
616
617
    sfd = DetectFlowintParse(de_ctx, "myvar,-,targetvar");
618
    DetectFlowintPrintData(sfd);
619
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
620
            && sfd->targettype == FLOWINT_TARGET_VAR
621
            && sfd->target.tvar.name != NULL
622
            && !strcmp(sfd->target.tvar.name, "targetvar")
623
            && sfd->modifier == FLOWINT_MODIFIER_SUB) {
624
625
        result = 1;
626
    }
627
    if (sfd) DetectFlowintFree(NULL, sfd);
628
    DetectEngineCtxFree(de_ctx);
629
630
    return result;
631
}
632
633
634
/**
635
 * \test DetectFlowintTestParseVal04 is a test to make sure that we set the
636
 *  DetectFlowint correctly for checking if equal to a valid target value
637
 */
638
static int DetectFlowintTestParseVal04(void)
639
{
640
    int result = 0;
641
    DetectFlowintData *sfd = NULL;
642
    DetectEngineCtx *de_ctx;
643
    de_ctx = DetectEngineCtxInit();
644
    if (de_ctx == NULL)
645
        return 0;
646
    de_ctx->flags |= DE_QUIET;
647
648
    sfd = DetectFlowintParse(de_ctx, "myvar,==,35");
649
    DetectFlowintPrintData(sfd);
650
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
651
            && sfd->modifier == FLOWINT_MODIFIER_EQ) {
652
        result = 1;
653
    }
654
    if (sfd) DetectFlowintFree(NULL, sfd);
655
656
    DetectEngineCtxFree(de_ctx);
657
658
    return result;
659
}
660
661
/**
662
 * \test DetectFlowintTestParseVar04 is a test to make sure that we set the
663
 *  DetectFlowint correctly for checking if equal to a valid target variable
664
 */
665
static int DetectFlowintTestParseVar04(void)
666
{
667
    int result = 0;
668
    DetectFlowintData *sfd = NULL;
669
    DetectEngineCtx *de_ctx;
670
    de_ctx = DetectEngineCtxInit();
671
    if (de_ctx == NULL)
672
        return 0;
673
    de_ctx->flags |= DE_QUIET;
674
675
    sfd = DetectFlowintParse(de_ctx, "myvar,==,targetvar");
676
    DetectFlowintPrintData(sfd);
677
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
678
            && sfd->targettype == FLOWINT_TARGET_VAR
679
            && sfd->target.tvar.name != NULL
680
            && !strcmp(sfd->target.tvar.name, "targetvar")
681
            && sfd->modifier == FLOWINT_MODIFIER_EQ) {
682
683
        result = 1;
684
    }
685
    if (sfd) DetectFlowintFree(NULL, sfd);
686
    DetectEngineCtxFree(de_ctx);
687
688
    return result;
689
}
690
691
/**
692
 * \test DetectFlowintTestParseVal05 is a test to make sure that we set the
693
 *  DetectFlowint correctly for checking if not equal to a valid target value
694
 */
695
static int DetectFlowintTestParseVal05(void)
696
{
697
    int result = 0;
698
    DetectFlowintData *sfd = NULL;
699
    DetectEngineCtx *de_ctx;
700
    de_ctx = DetectEngineCtxInit();
701
    if (de_ctx == NULL)
702
        return 0;
703
    de_ctx->flags |= DE_QUIET;
704
705
    sfd = DetectFlowintParse(de_ctx, "myvar,!=,35");
706
    DetectFlowintPrintData(sfd);
707
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
708
            && sfd->modifier == FLOWINT_MODIFIER_NE) {
709
        result = 1;
710
    }
711
    if (sfd) DetectFlowintFree(NULL, sfd);
712
713
    DetectEngineCtxFree(de_ctx);
714
715
    return result;
716
}
717
718
/**
719
 * \test DetectFlowintTestParseVar05 is a test to make sure that we set the
720
 *  DetectFlowint correctly for checking if not equal to a valid target variable
721
 */
722
static int DetectFlowintTestParseVar05(void)
723
{
724
    int result = 0;
725
    DetectFlowintData *sfd = NULL;
726
    DetectEngineCtx *de_ctx;
727
    de_ctx = DetectEngineCtxInit();
728
    if (de_ctx == NULL)
729
        return 0;
730
    de_ctx->flags |= DE_QUIET;
731
732
    sfd = DetectFlowintParse(de_ctx, "myvar,!=,targetvar");
733
    DetectFlowintPrintData(sfd);
734
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
735
            && sfd->targettype == FLOWINT_TARGET_VAR
736
            && sfd->target.tvar.name != NULL
737
            && !strcmp(sfd->target.tvar.name, "targetvar")
738
            && sfd->modifier == FLOWINT_MODIFIER_NE) {
739
740
        result = 1;
741
    }
742
    if (sfd) DetectFlowintFree(NULL, sfd);
743
    DetectEngineCtxFree(de_ctx);
744
745
    return result;
746
}
747
748
/**
749
 * \test DetectFlowintTestParseVal06 is a test to make sure that we set the
750
 *  DetectFlowint correctly for checking if greater than a valid target value
751
 */
752
static int DetectFlowintTestParseVal06(void)
753
{
754
    int result = 0;
755
    DetectFlowintData *sfd = NULL;
756
    DetectEngineCtx *de_ctx;
757
    de_ctx = DetectEngineCtxInit();
758
    if (de_ctx == NULL)
759
        return 0;
760
    de_ctx->flags |= DE_QUIET;
761
762
    sfd = DetectFlowintParse(de_ctx, "myvar, >,35");
763
    DetectFlowintPrintData(sfd);
764
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
765
            && sfd->modifier == FLOWINT_MODIFIER_GT) {
766
        result = 1;
767
    }
768
    if (sfd) DetectFlowintFree(NULL, sfd);
769
770
    DetectEngineCtxFree(de_ctx);
771
772
    return result;
773
}
774
775
/**
776
 * \test DetectFlowintTestParseVar06 is a test to make sure that we set the
777
 *  DetectFlowint correctly for checking if greater than a valid target variable
778
 */
779
static int DetectFlowintTestParseVar06(void)
780
{
781
    int result = 0;
782
    DetectFlowintData *sfd = NULL;
783
    DetectEngineCtx *de_ctx;
784
    de_ctx = DetectEngineCtxInit();
785
    if (de_ctx == NULL)
786
        return 0;
787
    de_ctx->flags |= DE_QUIET;
788
789
    sfd = DetectFlowintParse(de_ctx, "myvar, >,targetvar");
790
    DetectFlowintPrintData(sfd);
791
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
792
            && sfd->targettype == FLOWINT_TARGET_VAR
793
            && sfd->target.tvar.name != NULL
794
            && !strcmp(sfd->target.tvar.name, "targetvar")
795
            && sfd->modifier == FLOWINT_MODIFIER_GT) {
796
797
        result = 1;
798
    }
799
    if (sfd) DetectFlowintFree(NULL, sfd);
800
    DetectEngineCtxFree(de_ctx);
801
802
    return result;
803
}
804
805
/**
806
 * \test DetectFlowintTestParseVal07 is a test to make sure that we set the
807
 *  DetectFlowint correctly for checking if greater or equal than a valid target value
808
 */
809
static int DetectFlowintTestParseVal07(void)
810
{
811
    int result = 0;
812
    DetectFlowintData *sfd = NULL;
813
    DetectEngineCtx *de_ctx;
814
    de_ctx = DetectEngineCtxInit();
815
    if (de_ctx == NULL)
816
        return 0;
817
    de_ctx->flags |= DE_QUIET;
818
819
    sfd = DetectFlowintParse(de_ctx, "myvar, >= ,35");
820
    DetectFlowintPrintData(sfd);
821
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
822
            && sfd->modifier == FLOWINT_MODIFIER_GE) {
823
        result = 1;
824
    }
825
    if (sfd) DetectFlowintFree(NULL, sfd);
826
827
    DetectEngineCtxFree(de_ctx);
828
829
    return result;
830
}
831
832
/**
833
 * \test DetectFlowintTestParseVar07 is a test to make sure that we set the
834
 *  DetectFlowint correctly for checking if greater or equal than a valid target variable
835
 */
836
static int DetectFlowintTestParseVar07(void)
837
{
838
    int result = 0;
839
    DetectFlowintData *sfd = NULL;
840
    DetectEngineCtx *de_ctx;
841
    de_ctx = DetectEngineCtxInit();
842
    if (de_ctx == NULL)
843
        return 0;
844
    de_ctx->flags |= DE_QUIET;
845
846
    sfd = DetectFlowintParse(de_ctx, "myvar, >= ,targetvar");
847
    DetectFlowintPrintData(sfd);
848
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
849
            && sfd->targettype == FLOWINT_TARGET_VAR
850
            && sfd->target.tvar.name != NULL
851
            && !strcmp(sfd->target.tvar.name, "targetvar")
852
            && sfd->modifier == FLOWINT_MODIFIER_GE) {
853
854
        result = 1;
855
    }
856
    if (sfd) DetectFlowintFree(NULL, sfd);
857
    DetectEngineCtxFree(de_ctx);
858
859
    return result;
860
}
861
862
/**
863
 * \test DetectFlowintTestParseVal08 is a test to make sure that we set the
864
 *  DetectFlowint correctly for checking if lower or equal than a valid target value
865
 */
866
static int DetectFlowintTestParseVal08(void)
867
{
868
    int result = 0;
869
    DetectFlowintData *sfd = NULL;
870
    DetectEngineCtx *de_ctx;
871
    de_ctx = DetectEngineCtxInit();
872
    if (de_ctx == NULL)
873
        return 0;
874
    de_ctx->flags |= DE_QUIET;
875
876
    sfd = DetectFlowintParse(de_ctx, "myvar, <= ,35");
877
    DetectFlowintPrintData(sfd);
878
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
879
            && sfd->modifier == FLOWINT_MODIFIER_LE) {
880
        result = 1;
881
    }
882
    if (sfd) DetectFlowintFree(NULL, sfd);
883
884
    DetectEngineCtxFree(de_ctx);
885
886
    return result;
887
}
888
889
/**
890
 * \test DetectFlowintTestParseVar08 is a test to make sure that we set the
891
 *  DetectFlowint correctly for checking if lower or equal than a valid target variable
892
 */
893
static int DetectFlowintTestParseVar08(void)
894
{
895
    int result = 0;
896
    DetectFlowintData *sfd = NULL;
897
    DetectEngineCtx *de_ctx;
898
    de_ctx = DetectEngineCtxInit();
899
    if (de_ctx == NULL)
900
        return 0;
901
    de_ctx->flags |= DE_QUIET;
902
903
    sfd = DetectFlowintParse(de_ctx, "myvar, <= ,targetvar");
904
    DetectFlowintPrintData(sfd);
905
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
906
            && sfd->targettype == FLOWINT_TARGET_VAR
907
            && sfd->target.tvar.name != NULL
908
            && !strcmp(sfd->target.tvar.name, "targetvar")
909
            && sfd->modifier == FLOWINT_MODIFIER_LE) {
910
911
        result = 1;
912
    }
913
    if (sfd) DetectFlowintFree(NULL, sfd);
914
    DetectEngineCtxFree(de_ctx);
915
916
    return result;
917
}
918
919
/**
920
 * \test DetectFlowintTestParseVal09 is a test to make sure that we set the
921
 *  DetectFlowint correctly for checking if lower than a valid target value
922
 */
923
static int DetectFlowintTestParseVal09(void)
924
{
925
    int result = 0;
926
    DetectFlowintData *sfd = NULL;
927
    DetectEngineCtx *de_ctx;
928
    de_ctx = DetectEngineCtxInit();
929
    if (de_ctx == NULL)
930
        return 0;
931
    de_ctx->flags |= DE_QUIET;
932
933
    sfd = DetectFlowintParse(de_ctx, "myvar, < ,35");
934
    DetectFlowintPrintData(sfd);
935
    if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
936
            && sfd->modifier == FLOWINT_MODIFIER_LT) {
937
        result = 1;
938
    }
939
    if (sfd) DetectFlowintFree(NULL, sfd);
940
941
    DetectEngineCtxFree(de_ctx);
942
943
    return result;
944
}
945
946
/**
947
 * \test DetectFlowintTestParseVar09 is a test to make sure that we set the
948
 *  DetectFlowint correctly for checking if lower than a valid target variable
949
 */
950
static int DetectFlowintTestParseVar09(void)
951
{
952
    int result = 0;
953
    DetectFlowintData *sfd = NULL;
954
    DetectEngineCtx *de_ctx;
955
    de_ctx = DetectEngineCtxInit();
956
    if (de_ctx == NULL)
957
        return 0;
958
    de_ctx->flags |= DE_QUIET;
959
960
    sfd = DetectFlowintParse(de_ctx, "myvar, < ,targetvar");
961
    DetectFlowintPrintData(sfd);
962
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
963
            && sfd->targettype == FLOWINT_TARGET_VAR
964
            && sfd->target.tvar.name != NULL
965
            && !strcmp(sfd->target.tvar.name, "targetvar")
966
            && sfd->modifier == FLOWINT_MODIFIER_LT) {
967
968
        result = 1;
969
    }
970
    if (sfd) DetectFlowintFree(NULL, sfd);
971
    DetectEngineCtxFree(de_ctx);
972
973
    return result;
974
}
975
976
/**
977
 * \test DetectFlowintTestParseVar09 is a test to make sure that handle the
978
 * isset keyword correctly
979
 */
980
static int DetectFlowintTestParseIsset10(void)
981
{
982
    int result = 1;
983
    DetectFlowintData *sfd = NULL;
984
    DetectEngineCtx *de_ctx;
985
    de_ctx = DetectEngineCtxInit();
986
    if (de_ctx == NULL)
987
        return 0;
988
    de_ctx->flags |= DE_QUIET;
989
990
    sfd = DetectFlowintParse(de_ctx, "myvar, isset");
991
    DetectFlowintPrintData(sfd);
992
    if (sfd != NULL && !strcmp(sfd->name, "myvar")
993
            && sfd->targettype == FLOWINT_TARGET_SELF
994
            && sfd->modifier == FLOWINT_MODIFIER_ISSET) {
995
996
        result &= 1;
997
    } else {
998
        result = 0;
999
    }
1000
1001
    if (sfd) DetectFlowintFree(NULL, sfd);
1002
    sfd = DetectFlowintParse(de_ctx, "myvar, notset");
1003
    DetectFlowintPrintData(sfd);
1004
    if (sfd != NULL && !strcmp(sfd->name, "myvar") && sfd->targettype == FLOWINT_TARGET_SELF &&
1005
            sfd->modifier == FLOWINT_MODIFIER_ISNOTSET) {
1006
1007
        result &= 1;
1008
    } else {
1009
        result = 0;
1010
    }
1011
1012
    if (sfd) DetectFlowintFree(NULL, sfd);
1013
    DetectEngineCtxFree(de_ctx);
1014
1015
    return result;
1016
}
1017
1018
/**
1019
 * \test DetectFlowintTestParseInvalidSyntaxis01 is a test to make sure that we dont set the
1020
 *  DetectFlowint for a invalid input option
1021
 */
1022
static int DetectFlowintTestParseInvalidSyntaxis01(void)
1023
{
1024
    int result = 1;
1025
    DetectFlowintData *sfd = NULL;
1026
    DetectEngineCtx *de_ctx;
1027
    de_ctx = DetectEngineCtxInit();
1028
    if (de_ctx == NULL)
1029
        goto error;
1030
    de_ctx->flags |= DE_QUIET;
1031
1032
    sfd = DetectFlowintParse(de_ctx, "myvar,=,9999999999");
1033
    if (sfd != NULL) {
1034
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=,9532458716234857");
1035
        result = 0;
1036
    }
1037
    if (sfd) DetectFlowintFree(NULL, sfd);
1038
1039
    sfd = DetectFlowintParse(de_ctx, "myvar,=,45targetvar");
1040
    if (sfd != NULL) {
1041
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=,45targetvar ");
1042
        result = 0;
1043
    }
1044
    if (sfd) DetectFlowintFree(NULL, sfd);
1045
1046
    sfd = DetectFlowintParse(de_ctx, "657myvar,=,targetvar");
1047
    if (sfd != NULL) {
1048
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at 657myvar,=,targetvar ");
1049
        result = 0;
1050
    }
1051
    if (sfd) DetectFlowintFree(NULL, sfd);
1052
1053
    sfd = DetectFlowintParse(de_ctx, "myvar,=<,targetvar");
1054
    if (sfd != NULL) {
1055
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=<,targetvar ");
1056
        result = 0;
1057
    }
1058
    if (sfd) DetectFlowintFree(NULL, sfd);
1059
1060
    sfd = DetectFlowintParse(de_ctx, "myvar,===,targetvar");
1061
    if (sfd != NULL) {
1062
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,===,targetvar ");
1063
        result = 0;
1064
    }
1065
    if (sfd) DetectFlowintFree(NULL, sfd);
1066
1067
    sfd = DetectFlowintParse(de_ctx, "myvar,==");
1068
    if (sfd != NULL) {
1069
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,==");
1070
        result = 0;
1071
    }
1072
    if (sfd) DetectFlowintFree(NULL, sfd);
1073
1074
    sfd = DetectFlowintParse(de_ctx, "myvar,");
1075
    if (sfd != NULL) {
1076
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,");
1077
        result = 0;
1078
    }
1079
    if (sfd) DetectFlowintFree(NULL, sfd);
1080
1081
    sfd = DetectFlowintParse(de_ctx, "myvar");
1082
    if (sfd != NULL) {
1083
        SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar");
1084
        result = 0;
1085
    }
1086
    if (sfd) DetectFlowintFree(NULL, sfd);
1087
1088
    DetectEngineCtxFree(de_ctx);
1089
1090
    return result;
1091
error:
1092
    if (de_ctx)
1093
        DetectEngineCtxFree(de_ctx);
1094
    return result;
1095
}
1096
1097
/** \test DetectFlowintTestPacket01Real
1098
 * \brief Set a counter when we see a content:"GET"
1099
 *        and increment it by 2 if we match a "Unauthorized"
1100
 *        When it reach 3(with the last +2), another counter starts
1101
 *        and when that counter reach 6 packets.
1102
 *
1103
 *        All the Signatures generate an alert(its for testing)
1104
 *        but the signature that increment the second counter +1, that has
1105
 *        a "noalert", so we can do all increments
1106
 *        silently until we reach 6 next packets counted
1107
 */
1108
static int DetectFlowintTestPacket01Real(void)
1109
{
1110
    Packet *p = NULL;
1111
    ThreadVars th_v;
1112
    DetectEngineThreadCtx *det_ctx = NULL;
1113
    memset(&th_v, 0, sizeof(th_v));
1114
1115
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1116
    FAIL_IF(de_ctx == NULL);
1117
1118
    de_ctx->flags |= DE_QUIET;
1119
1120
    const char *sigs[5];
1121
    sigs[0] = "alert tcp any any -> any any (msg:\"Setting a flowint counter\"; content:\"GET\"; flowint:myvar,=,1; flowint:maxvar,=,6; sid:101;)";
1122
    sigs[1] = "alert tcp any any -> any any (msg:\"Adding to flowint counter\"; content:\"Unauthorized\"; flowint: myvar,+,2; sid:102;)";
1123
    sigs[2] = "alert tcp any any -> any any (msg:\"if the flowint counter is 3 create a new counter\"; content:\"Unauthorized\"; flowint: myvar,==,3; flowint: cntpackets, =, 0; sid:103;)";
1124
    sigs[3] = "alert tcp any any -> any any (msg:\"and count the rest of the packets received without generating alerts!!!\"; flowint: myvar,==,3; flowint: cntpackets, +, 1; noalert;sid:104;)";
1125
    sigs[4] = "alert tcp any any -> any any (msg:\" and fire this when it reach 6\"; flowint: cntpackets, ==, maxvar; sid:105;)";
1126
    FAIL_IF(UTHAppendSigs(de_ctx, sigs, 5) == 0);
1127
1128
    SCSigRegisterSignatureOrderingFuncs(de_ctx);
1129
    SCSigOrderSignatures(de_ctx);
1130
    SCSigSignatureOrderingModuleCleanup(de_ctx);
1131
    SigGroupBuild(de_ctx);
1132
    DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1133
1134
    Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1135
            41424, 80);
1136
    FAIL_IF(f == NULL);
1137
    f->proto = IPPROTO_TCP;
1138
1139
    p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1140
    FAIL_IF(p == NULL);
1141
    UTHAssignFlow(p, f);
1142
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1143
    FAIL_IF(!PacketAlertCheck(p, 101));
1144
    UTHFreePacket(p);
1145
1146
    p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1147
    FAIL_IF(p == NULL);
1148
    UTHAssignFlow(p, f);
1149
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1150
    FAIL_IF(!PacketAlertCheck(p, 102));
1151
    FAIL_IF(!PacketAlertCheck(p, 103));
1152
    UTHFreePacket(p);
1153
1154
    p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1155
    FAIL_IF(p == NULL);
1156
    UTHAssignFlow(p, f);
1157
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1158
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1159
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1160
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1161
    UTHFreePacket(p);
1162
1163
    p = UTHBuildPacket((uint8_t *)"X", 1, IPPROTO_TCP);
1164
    FAIL_IF(p == NULL);
1165
    UTHAssignFlow(p, f);
1166
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1167
    FAIL_IF(!PacketAlertCheck(p, 105));
1168
    UTHFreePacket(p);
1169
1170
    UTHFreeFlow(f);
1171
    DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1172
    DetectEngineCtxFree(de_ctx);
1173
1174
    PASS;
1175
}
1176
1177
/**
1178
 * \test DetectFlowintTestPacket02Real
1179
 * \brief like DetectFlowintTestPacket01Real but using isset/notset keywords
1180
 */
1181
static int DetectFlowintTestPacket02Real(void)
1182
{
1183
    Packet *p = NULL;
1184
    ThreadVars th_v;
1185
    DetectEngineThreadCtx *det_ctx = NULL;
1186
    memset(&th_v, 0, sizeof(th_v));
1187
1188
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1189
    FAIL_IF(de_ctx == NULL);
1190
1191
    de_ctx->flags |= DE_QUIET;
1192
1193
    const char *sigs[5];
1194
    sigs[0] = "alert tcp any any -> any any (msg:\"Setting a flowint counter\"; content:\"GET\"; "
1195
              "flowint:myvar,notset; flowint:maxvar,isnotset; flowint: myvar,=,1; flowint: "
1196
              "maxvar,=,6; sid:101;)";
1197
    sigs[1] = "alert tcp any any -> any any (msg:\"Adding to flowint counter\"; content:\"Unauthorized\"; flowint:myvar,isset; flowint: myvar,+,2; sid:102;)";
1198
    sigs[2] = "alert tcp any any -> any any (msg:\"if the flowint counter is 3 create a new counter\"; content:\"Unauthorized\"; flowint: myvar, isset; flowint: myvar,==,3; flowint:cntpackets,notset; flowint: cntpackets, =, 0; sid:103;)";
1199
    sigs[3] = "alert tcp any any -> any any (msg:\"and count the rest of the packets received without generating alerts!!!\"; flowint: cntpackets,isset; flowint: cntpackets, +, 1; noalert;sid:104;)";
1200
    sigs[4] = "alert tcp any any -> any any (msg:\" and fire this when it reach 6\"; flowint: cntpackets, isset; flowint: maxvar,isset; flowint: cntpackets, ==, maxvar; sid:105;)";
1201
    FAIL_IF(UTHAppendSigs(de_ctx, sigs, 5) == 0);
1202
1203
    SCSigRegisterSignatureOrderingFuncs(de_ctx);
1204
    SCSigOrderSignatures(de_ctx);
1205
    SCSigSignatureOrderingModuleCleanup(de_ctx);
1206
    SigGroupBuild(de_ctx);
1207
    DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1208
1209
    Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1210
            41424, 80);
1211
    FAIL_IF(f == NULL);
1212
    f->proto = IPPROTO_TCP;
1213
1214
    p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1215
    FAIL_IF(p == NULL);
1216
    UTHAssignFlow(p, f);
1217
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1218
    FAIL_IF(!PacketAlertCheck(p, 101));
1219
    UTHFreePacket(p);
1220
1221
    p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1222
    FAIL_IF(p == NULL);
1223
    UTHAssignFlow(p, f);
1224
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1225
    FAIL_IF(!PacketAlertCheck(p, 102));
1226
    FAIL_IF(!PacketAlertCheck(p, 103));
1227
    UTHFreePacket(p);
1228
1229
    p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1230
    FAIL_IF(p == NULL);
1231
    UTHAssignFlow(p, f);
1232
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1233
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1234
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1235
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1236
    UTHFreePacket(p);
1237
1238
    p = UTHBuildPacket((uint8_t *)"X", 1, IPPROTO_TCP);
1239
    FAIL_IF(p == NULL);
1240
    UTHAssignFlow(p, f);
1241
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1242
    FAIL_IF(!PacketAlertCheck(p, 105));
1243
    UTHFreePacket(p);
1244
1245
    UTHFreeFlow(f);
1246
    DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1247
    DetectEngineCtxFree(de_ctx);
1248
1249
    PASS;
1250
}
1251
1252
/**
1253
 * \test DetectFlowintTestPacket03Real
1254
 * \brief Check the behaviour of isset/notset
1255
 */
1256
static int DetectFlowintTestPacket03Real(void)
1257
{
1258
    Packet *p = NULL;
1259
    ThreadVars th_v;
1260
    DetectEngineThreadCtx *det_ctx = NULL;
1261
    memset(&th_v, 0, sizeof(th_v));
1262
1263
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1264
    FAIL_IF(de_ctx == NULL);
1265
1266
    de_ctx->flags |= DE_QUIET;
1267
1268
    const char *sigs[3];
1269
    sigs[0] = "alert tcp any any -> any any (msg:\"check notset\"; content:\"GET\"; flowint: myvar, notset; flowint: myvar,=,0; flowint: other,=,10; sid:101;)";
1270
    sigs[1] = "alert tcp any any -> any any (msg:\"check isset\"; content:\"Unauthorized\"; flowint:myvar,isset; flowint: other,isset; sid:102;)";
1271
    sigs[2] = "alert tcp any any -> any any (msg:\"check notset\"; content:\"Unauthorized\"; flowint:lala,isset; sid:103;)";
1272
    FAIL_IF(UTHAppendSigs(de_ctx, sigs, 3) == 0);
1273
1274
    SCSigRegisterSignatureOrderingFuncs(de_ctx);
1275
    SCSigOrderSignatures(de_ctx);
1276
    SCSigSignatureOrderingModuleCleanup(de_ctx);
1277
    SigGroupBuild(de_ctx);
1278
    DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1279
1280
    Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1281
            41424, 80);
1282
    FAIL_IF(f == NULL);
1283
    f->proto = IPPROTO_TCP;
1284
1285
    p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1286
    FAIL_IF(p == NULL);
1287
    UTHAssignFlow(p, f);
1288
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1289
    FAIL_IF(!PacketAlertCheck(p, 101));
1290
    UTHFreePacket(p);
1291
1292
    p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1293
    FAIL_IF(p == NULL);
1294
    UTHAssignFlow(p, f);
1295
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1296
    FAIL_IF(!PacketAlertCheck(p, 102));
1297
    FAIL_IF(PacketAlertCheck(p, 103));
1298
    UTHFreePacket(p);
1299
1300
    p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1301
    FAIL_IF(p == NULL);
1302
    UTHAssignFlow(p, f);
1303
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1304
    FAIL_IF(PacketAlertCheck(p, 102));
1305
    FAIL_IF(PacketAlertCheck(p, 103));
1306
    UTHFreePacket(p);
1307
1308
    UTHFreeFlow(f);
1309
    DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1310
    DetectEngineCtxFree(de_ctx);
1311
1312
    PASS;
1313
}
1314
1315
/**
1316
 * \brief this function registers unit tests for DetectFlowint
1317
 */
1318
void DetectFlowintRegisterTests(void)
1319
{
1320
    UtRegisterTest("DetectFlowintTestParseVal01", DetectFlowintTestParseVal01);
1321
    UtRegisterTest("DetectFlowintTestParseVar01", DetectFlowintTestParseVar01);
1322
    UtRegisterTest("DetectFlowintTestParseVal02", DetectFlowintTestParseVal02);
1323
    UtRegisterTest("DetectFlowintTestParseVar02", DetectFlowintTestParseVar02);
1324
    UtRegisterTest("DetectFlowintTestParseVal03", DetectFlowintTestParseVal03);
1325
    UtRegisterTest("DetectFlowintTestParseVar03", DetectFlowintTestParseVar03);
1326
    UtRegisterTest("DetectFlowintTestParseVal04", DetectFlowintTestParseVal04);
1327
    UtRegisterTest("DetectFlowintTestParseVar04", DetectFlowintTestParseVar04);
1328
    UtRegisterTest("DetectFlowintTestParseVal05", DetectFlowintTestParseVal05);
1329
    UtRegisterTest("DetectFlowintTestParseVar05", DetectFlowintTestParseVar05);
1330
    UtRegisterTest("DetectFlowintTestParseVal06", DetectFlowintTestParseVal06);
1331
    UtRegisterTest("DetectFlowintTestParseVar06", DetectFlowintTestParseVar06);
1332
    UtRegisterTest("DetectFlowintTestParseVal07", DetectFlowintTestParseVal07);
1333
    UtRegisterTest("DetectFlowintTestParseVar07", DetectFlowintTestParseVar07);
1334
    UtRegisterTest("DetectFlowintTestParseVal08", DetectFlowintTestParseVal08);
1335
    UtRegisterTest("DetectFlowintTestParseVar08", DetectFlowintTestParseVar08);
1336
    UtRegisterTest("DetectFlowintTestParseVal09", DetectFlowintTestParseVal09);
1337
    UtRegisterTest("DetectFlowintTestParseVar09", DetectFlowintTestParseVar09);
1338
    UtRegisterTest("DetectFlowintTestParseIsset10",
1339
                   DetectFlowintTestParseIsset10);
1340
    UtRegisterTest("DetectFlowintTestParseInvalidSyntaxis01",
1341
                   DetectFlowintTestParseInvalidSyntaxis01);
1342
    UtRegisterTest("DetectFlowintTestPacket01Real",
1343
                   DetectFlowintTestPacket01Real);
1344
    UtRegisterTest("DetectFlowintTestPacket02Real",
1345
                   DetectFlowintTestPacket02Real);
1346
    UtRegisterTest("DetectFlowintTestPacket03Real",
1347
                   DetectFlowintTestPacket03Real);
1348
}
1349
#endif /* UNITTESTS */