/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 */ |