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