Coverage Report

Created: 2026-06-30 07:20

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