/src/suricata7/src/detect-csum.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2022 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 Anoop Saldanha <anoopsaldanha@gmail.com> |
22 | | * |
23 | | * Implements checksum keyword. |
24 | | */ |
25 | | |
26 | | #include "suricata-common.h" |
27 | | #include "decode.h" |
28 | | |
29 | | #include "detect.h" |
30 | | #include "detect-parse.h" |
31 | | |
32 | | #include "detect-csum.h" |
33 | | |
34 | | #include "util-unittest.h" |
35 | | #include "util-debug.h" |
36 | | |
37 | | #include "pkt-var.h" |
38 | | #include "host.h" |
39 | | #include "util-profiling.h" |
40 | | #include "detect-engine-build.h" |
41 | | |
42 | 7.58k | #define DETECT_CSUM_VALID "valid" |
43 | 3.29k | #define DETECT_CSUM_INVALID "invalid" |
44 | | |
45 | | typedef struct DetectCsumData_ { |
46 | | /* Indicates if the csum-<protocol> keyword in a rule holds the |
47 | | keyvalue "valid" or "invalid" */ |
48 | | int16_t valid; |
49 | | } DetectCsumData; |
50 | | |
51 | | /* prototypes for the "ipv4-csum" rule keyword */ |
52 | | static int DetectIPV4CsumMatch(DetectEngineThreadCtx *, |
53 | | Packet *, const Signature *, const SigMatchCtx *); |
54 | | static int DetectIPV4CsumSetup(DetectEngineCtx *, Signature *, const char *); |
55 | | static void DetectIPV4CsumFree(DetectEngineCtx *, void *); |
56 | | |
57 | | /* prototypes for the "tcpv4-csum" rule keyword */ |
58 | | static int DetectTCPV4CsumMatch(DetectEngineThreadCtx *, |
59 | | Packet *, const Signature *, const SigMatchCtx *); |
60 | | static int DetectTCPV4CsumSetup(DetectEngineCtx *, Signature *, const char *); |
61 | | static void DetectTCPV4CsumFree(DetectEngineCtx *, void *); |
62 | | |
63 | | /* prototypes for the "tcpv6-csum" rule keyword */ |
64 | | static int DetectTCPV6CsumMatch(DetectEngineThreadCtx *, |
65 | | Packet *, const Signature *, const SigMatchCtx *); |
66 | | static int DetectTCPV6CsumSetup(DetectEngineCtx *, Signature *, const char *); |
67 | | static void DetectTCPV6CsumFree(DetectEngineCtx *, void *); |
68 | | |
69 | | /* prototypes for the "udpv4-csum" rule keyword */ |
70 | | static int DetectUDPV4CsumMatch(DetectEngineThreadCtx *, |
71 | | Packet *, const Signature *, const SigMatchCtx *); |
72 | | static int DetectUDPV4CsumSetup(DetectEngineCtx *, Signature *, const char *); |
73 | | static void DetectUDPV4CsumFree(DetectEngineCtx *, void *); |
74 | | |
75 | | /* prototypes for the "udpv6-csum" rule keyword */ |
76 | | static int DetectUDPV6CsumMatch(DetectEngineThreadCtx *, |
77 | | Packet *, const Signature *, const SigMatchCtx *); |
78 | | static int DetectUDPV6CsumSetup(DetectEngineCtx *, Signature *, const char *); |
79 | | static void DetectUDPV6CsumFree(DetectEngineCtx *de_ctx, void *); |
80 | | |
81 | | /* prototypes for the "icmpv4-csum" rule keyword */ |
82 | | static int DetectICMPV4CsumMatch(DetectEngineThreadCtx *, |
83 | | Packet *, const Signature *, const SigMatchCtx *); |
84 | | static int DetectICMPV4CsumSetup(DetectEngineCtx *, Signature *, const char *); |
85 | | static void DetectICMPV4CsumFree(DetectEngineCtx *, void *); |
86 | | |
87 | | /* prototypes for the "icmpv6-csum" rule keyword */ |
88 | | static int DetectICMPV6CsumMatch(DetectEngineThreadCtx *, |
89 | | Packet *, const Signature *, const SigMatchCtx *); |
90 | | static int DetectICMPV6CsumSetup(DetectEngineCtx *, Signature *, const char *); |
91 | | static void DetectICMPV6CsumFree(DetectEngineCtx *, void *); |
92 | | |
93 | | #ifdef UNITTESTS |
94 | | static void DetectCsumRegisterTests(void); |
95 | | #endif |
96 | | |
97 | | /** |
98 | | * \brief Registers handlers for all the checksum keywords. The checksum |
99 | | * keywords that are registered are ipv4-sum, tcpv4-csum, tcpv6-csum, |
100 | | * udpv4-csum, udpv6-csum, icmpv4-csum and icmpv6-csum. |
101 | | * |
102 | | * Each of the checksum keywords implemented here takes 2 arguments - |
103 | | * "valid" or "invalid". If the rule keyword in the signature is |
104 | | * specified as "valid", the Match function would return TRUE if the |
105 | | * checksum for that particular packet and protocol is valid. Similarly |
106 | | * for "invalid". |
107 | | * |
108 | | * The Setup functions takes 4 arguments - |
109 | | * |
110 | | * DetectEngineCtx * (de_ctx) - A pointer to the detection engine context |
111 | | * Signature *(s) - Pointer to signature for the current Signature being |
112 | | * parsed from the rules |
113 | | * SigMatchCtx * (m) - Pointer to the head of the SigMatchs added to the |
114 | | * current Signature being parsed |
115 | | * char * (csum_str) - Pointer to a string holding the keyword value |
116 | | * |
117 | | * The Setup function returns 0 if it successfully parses the keyword |
118 | | * value, and -1 otherwise. |
119 | | * |
120 | | * The Match function takes 5 arguments - |
121 | | * |
122 | | * ThreadVars * (t) - Pointer to the tv for the detection module instance |
123 | | * DetectEngineThreadCtx * (det_ctx) - Pointer to the detection engine |
124 | | * thread context |
125 | | * Packet * (p) - Pointer to the Packet currently being handled |
126 | | * Signature * (s) - Pointer to the Signature, the packet is being |
127 | | * currently matched with |
128 | | * SigMatchCtx * (m) - Pointer to the keyword structure from the above |
129 | | * Signature, the Packet is being currently matched |
130 | | * with |
131 | | * |
132 | | * The Match function returns 1 if the Packet contents match the keyword, |
133 | | * and 0 otherwise |
134 | | * |
135 | | * The Free function takes a single argument - |
136 | | * |
137 | | * void * (ptr) - Pointer to the DetectCsumData for a keyword |
138 | | */ |
139 | | void DetectCsumRegister (void) |
140 | 73 | { |
141 | 73 | sigmatch_table[DETECT_IPV4_CSUM].name = "ipv4-csum"; |
142 | 73 | sigmatch_table[DETECT_IPV4_CSUM].Match = DetectIPV4CsumMatch; |
143 | 73 | sigmatch_table[DETECT_IPV4_CSUM].Setup = DetectIPV4CsumSetup; |
144 | 73 | sigmatch_table[DETECT_IPV4_CSUM].Free = DetectIPV4CsumFree; |
145 | | #ifdef UNITTESTS |
146 | | sigmatch_table[DETECT_IPV4_CSUM].RegisterTests = DetectCsumRegisterTests; |
147 | | #endif |
148 | | |
149 | 73 | sigmatch_table[DETECT_TCPV4_CSUM].name = "tcpv4-csum"; |
150 | 73 | sigmatch_table[DETECT_TCPV4_CSUM].Match = DetectTCPV4CsumMatch; |
151 | 73 | sigmatch_table[DETECT_TCPV4_CSUM].Setup = DetectTCPV4CsumSetup; |
152 | 73 | sigmatch_table[DETECT_TCPV4_CSUM].Free = DetectTCPV4CsumFree; |
153 | | |
154 | 73 | sigmatch_table[DETECT_TCPV6_CSUM].name = "tcpv6-csum"; |
155 | 73 | sigmatch_table[DETECT_TCPV6_CSUM].Match = DetectTCPV6CsumMatch; |
156 | 73 | sigmatch_table[DETECT_TCPV6_CSUM].Setup = DetectTCPV6CsumSetup; |
157 | 73 | sigmatch_table[DETECT_TCPV6_CSUM].Free = DetectTCPV6CsumFree; |
158 | | |
159 | 73 | sigmatch_table[DETECT_UDPV4_CSUM].name = "udpv4-csum"; |
160 | 73 | sigmatch_table[DETECT_UDPV4_CSUM].Match = DetectUDPV4CsumMatch; |
161 | 73 | sigmatch_table[DETECT_UDPV4_CSUM].Setup = DetectUDPV4CsumSetup; |
162 | 73 | sigmatch_table[DETECT_UDPV4_CSUM].Free = DetectUDPV4CsumFree; |
163 | | |
164 | 73 | sigmatch_table[DETECT_UDPV6_CSUM].name = "udpv6-csum"; |
165 | 73 | sigmatch_table[DETECT_UDPV6_CSUM].Match = DetectUDPV6CsumMatch; |
166 | 73 | sigmatch_table[DETECT_UDPV6_CSUM].Setup = DetectUDPV6CsumSetup; |
167 | 73 | sigmatch_table[DETECT_UDPV6_CSUM].Free = DetectUDPV6CsumFree; |
168 | | |
169 | 73 | sigmatch_table[DETECT_ICMPV4_CSUM].name = "icmpv4-csum"; |
170 | 73 | sigmatch_table[DETECT_ICMPV4_CSUM].Match = DetectICMPV4CsumMatch; |
171 | 73 | sigmatch_table[DETECT_ICMPV4_CSUM].Setup = DetectICMPV4CsumSetup; |
172 | 73 | sigmatch_table[DETECT_ICMPV4_CSUM].Free = DetectICMPV4CsumFree; |
173 | | |
174 | 73 | sigmatch_table[DETECT_ICMPV6_CSUM].name = "icmpv6-csum"; |
175 | 73 | sigmatch_table[DETECT_ICMPV6_CSUM].Match = DetectICMPV6CsumMatch; |
176 | 73 | sigmatch_table[DETECT_ICMPV6_CSUM].Setup = DetectICMPV6CsumSetup; |
177 | 73 | sigmatch_table[DETECT_ICMPV6_CSUM].Free = DetectICMPV6CsumFree; |
178 | 73 | } |
179 | | |
180 | | /** |
181 | | * \brief Validates and parses the argument supplied with the checksum keyword. |
182 | | * Accepts strings both with and without quotes, i.e. valid, \"valid\", |
183 | | * invalid and \"invalid\" |
184 | | * |
185 | | * \param key Pointer to a const character string holding the csum keyword value |
186 | | * \param cd Pointer to the DetectCsumData structure that holds the keyword |
187 | | * value sent as argument |
188 | | * |
189 | | * \retval 1 the keyvalue has been parsed successfully |
190 | | * \retval 0 error |
191 | | */ |
192 | | static int DetectCsumParseArg(const char *key, DetectCsumData *cd) |
193 | 3.89k | { |
194 | 3.89k | char *str; |
195 | | |
196 | 3.89k | if (key[0] == '\"' && key[strlen(key) - 1] == '\"') { |
197 | 0 | str = SCStrdup(key + 1); |
198 | 0 | if (unlikely(str == NULL)) { |
199 | 0 | goto error; |
200 | 0 | } |
201 | 0 | str[strlen(key) - 2] = '\0'; |
202 | 3.89k | } else { |
203 | 3.89k | str = SCStrdup(key); |
204 | 3.89k | if (unlikely(str == NULL)) { |
205 | 0 | goto error; |
206 | 0 | } |
207 | 3.89k | } |
208 | | |
209 | 3.89k | if (strcasecmp(str, DETECT_CSUM_VALID) == 0 || |
210 | 3.69k | strcasecmp(str, DETECT_CSUM_INVALID) == 0) { |
211 | 3.69k | cd->valid = (strcasecmp(key, DETECT_CSUM_VALID) == 0); |
212 | 3.69k | SCFree(str); |
213 | 3.69k | return 1; |
214 | 3.69k | } |
215 | | |
216 | 198 | error: |
217 | 198 | if (str != NULL) |
218 | 198 | SCFree(str); |
219 | 198 | return 0; |
220 | 3.89k | } |
221 | | |
222 | | /** |
223 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
224 | | * ipv4 checksum, based on whether ipv4-csum option for this rule |
225 | | * has been supplied with "valid" or "invalid" argument |
226 | | * |
227 | | * \param t Pointer to the tv for this detection module instance |
228 | | * \param det_ctx Pointer to the detection engine thread context |
229 | | * \param p Pointer to the Packet currently being matched |
230 | | * \param s Pointer to the Signature, the packet is being currently |
231 | | * matched with |
232 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
233 | | * Signature, the Packet is being currently matched with |
234 | | * |
235 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
236 | | */ |
237 | | static int DetectIPV4CsumMatch(DetectEngineThreadCtx *det_ctx, |
238 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
239 | 39.8k | { |
240 | 39.8k | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
241 | | |
242 | 39.8k | if (p->ip4h == NULL || PKT_IS_PSEUDOPKT(p)) |
243 | 2.24k | return 0; |
244 | | |
245 | 37.6k | if (p->flags & PKT_IGNORE_CHECKSUM) { |
246 | 0 | return cd->valid; |
247 | 0 | } |
248 | | |
249 | 37.6k | if (p->level3_comp_csum == -1) |
250 | 37.5k | p->level3_comp_csum = IPV4Checksum((uint16_t *)p->ip4h, |
251 | 37.5k | IPV4_GET_HLEN(p), |
252 | 37.5k | p->ip4h->ip_csum); |
253 | | |
254 | 37.6k | if (p->level3_comp_csum == 0 && cd->valid == 1) |
255 | 0 | return 1; |
256 | 37.6k | else if (p->level3_comp_csum != 0 && cd->valid == 0) |
257 | 24.0k | return 1; |
258 | 13.5k | else |
259 | 13.5k | return 0; |
260 | 37.6k | } |
261 | | |
262 | | /** |
263 | | * \brief Creates a SigMatch for the ipv4-csum keyword being sent as argument, |
264 | | * and appends it to the Signature(s). Accepts 2 values for the |
265 | | * keyword - "valid" and "invalid", both with and without quotes |
266 | | * |
267 | | * \param de_ctx Pointer to the detection engine context |
268 | | * \param s Pointer to signature for the current Signature being parsed |
269 | | * from the rules |
270 | | * \param csum_str Pointer to the string holding the keyword value |
271 | | * |
272 | | * \retval 0 on success, -1 on failure |
273 | | */ |
274 | | static int DetectIPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
275 | 537 | { |
276 | 537 | DetectCsumData *cd = NULL; |
277 | 537 | SigMatch *sm = NULL; |
278 | | |
279 | | //printf("DetectCsumSetup: \'%s\'\n", csum_str); |
280 | | |
281 | 537 | sm = SigMatchAlloc(); |
282 | 537 | if (sm == NULL) |
283 | 0 | goto error; |
284 | | |
285 | 537 | sm->type = DETECT_IPV4_CSUM; |
286 | | |
287 | 537 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
288 | 0 | goto error; |
289 | 537 | memset(cd, 0, sizeof(DetectCsumData)); |
290 | | |
291 | 537 | if (DetectCsumParseArg(csum_str, cd) == 0) |
292 | 14 | goto error; |
293 | | |
294 | 523 | sm->ctx = (SigMatchCtx *)cd; |
295 | | |
296 | 523 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
297 | | |
298 | 523 | return 0; |
299 | | |
300 | 14 | error: |
301 | 14 | if (cd != NULL) DetectIPV4CsumFree(de_ctx, cd); |
302 | 14 | if (sm != NULL) SCFree(sm); |
303 | | |
304 | 14 | return -1; |
305 | 537 | } |
306 | | |
307 | | static void DetectIPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
308 | 537 | { |
309 | 537 | DetectCsumData *cd = (DetectCsumData *)ptr; |
310 | | |
311 | 537 | if (cd != NULL) |
312 | 537 | SCFree(cd); |
313 | | |
314 | 537 | return; |
315 | 537 | } |
316 | | |
317 | | /** |
318 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
319 | | * tcpv4 checksum, based on whether tcpv4-csum option for this rule |
320 | | * has been supplied with "valid" or "invalid" argument |
321 | | * |
322 | | * \param t Pointer to the tv for this detection module instance |
323 | | * \param det_ctx Pointer to the detection engine thread context |
324 | | * \param p Pointer to the Packet currently being matched |
325 | | * \param s Pointer to the Signature, the packet is being currently |
326 | | * matched with |
327 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
328 | | * Signature, the Packet is being currently matched with |
329 | | * |
330 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
331 | | */ |
332 | | static int DetectTCPV4CsumMatch(DetectEngineThreadCtx *det_ctx, |
333 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
334 | 15.8k | { |
335 | 15.8k | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
336 | | |
337 | 15.8k | if (p->ip4h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p)) |
338 | 1.11k | return 0; |
339 | | |
340 | 14.7k | if (p->flags & PKT_IGNORE_CHECKSUM) { |
341 | 0 | return cd->valid; |
342 | 0 | } |
343 | | |
344 | 14.7k | if (p->level4_comp_csum == -1) |
345 | 14.7k | p->level4_comp_csum = TCPChecksum(p->ip4h->s_ip_addrs, |
346 | 14.7k | (uint16_t *)p->tcph, |
347 | 14.7k | (p->payload_len + |
348 | 14.7k | TCP_GET_HLEN(p)), |
349 | 14.7k | p->tcph->th_sum); |
350 | | |
351 | 14.7k | if (p->level4_comp_csum == 0 && cd->valid == 1) |
352 | 0 | return 1; |
353 | 14.7k | else if (p->level4_comp_csum != 0 && cd->valid == 0) |
354 | 10.2k | return 1; |
355 | 4.49k | else |
356 | 4.49k | return 0; |
357 | 14.7k | } |
358 | | |
359 | | /** |
360 | | * \brief Creates a SigMatch for the tcpv4-csum keyword being sent as argument, |
361 | | * and appends it to the Signature(s). Accepts 2 values for the |
362 | | * keyword - "valid" and "invalid", both with and without quotes |
363 | | * |
364 | | * \param de_ctx Pointer to the detection engine context |
365 | | * \param s Pointer to signature for the current Signature being parsed |
366 | | * from the rules |
367 | | * \param csum_str Pointer to the string holding the keyword value |
368 | | * |
369 | | * \retval 0 on success, -1 on failure |
370 | | */ |
371 | | static int DetectTCPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
372 | 476 | { |
373 | 476 | DetectCsumData *cd = NULL; |
374 | 476 | SigMatch *sm = NULL; |
375 | | |
376 | | //printf("DetectCsumSetup: \'%s\'\n", csum_str); |
377 | | |
378 | 476 | sm = SigMatchAlloc(); |
379 | 476 | if (sm == NULL) |
380 | 0 | goto error; |
381 | | |
382 | 476 | sm->type = DETECT_TCPV4_CSUM; |
383 | | |
384 | 476 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
385 | 0 | goto error; |
386 | 476 | memset(cd, 0, sizeof(DetectCsumData)); |
387 | | |
388 | 476 | if (DetectCsumParseArg(csum_str, cd) == 0) |
389 | 39 | goto error; |
390 | | |
391 | 437 | sm->ctx = (SigMatchCtx *)cd; |
392 | | |
393 | 437 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
394 | | |
395 | 437 | return 0; |
396 | | |
397 | 39 | error: |
398 | 39 | if (cd != NULL) DetectTCPV4CsumFree(de_ctx, cd); |
399 | 39 | if (sm != NULL) SCFree(sm); |
400 | | |
401 | 39 | return -1; |
402 | 476 | } |
403 | | |
404 | | static void DetectTCPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
405 | 476 | { |
406 | 476 | DetectCsumData *cd = (DetectCsumData *)ptr; |
407 | | |
408 | 476 | if (cd != NULL) |
409 | 476 | SCFree(cd); |
410 | | |
411 | 476 | return; |
412 | 476 | } |
413 | | |
414 | | /** |
415 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
416 | | * tcpv6 checksum, based on whether tcpv6-csum option for this rule |
417 | | * has been supplied with "valid" or "invalid" argument |
418 | | * |
419 | | * \param t Pointer to the tv for this detection module instance |
420 | | * \param det_ctx Pointer to the detection engine thread context |
421 | | * \param p Pointer to the Packet currently being matched |
422 | | * \param s Pointer to the Signature, the packet is being currently |
423 | | * matched with |
424 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
425 | | * Signature, the Packet is being currently matched with |
426 | | * |
427 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
428 | | */ |
429 | | static int DetectTCPV6CsumMatch(DetectEngineThreadCtx *det_ctx, |
430 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
431 | 7.64k | { |
432 | 7.64k | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
433 | | |
434 | 7.64k | if (p->ip6h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p)) |
435 | 7.45k | return 0; |
436 | | |
437 | 194 | if (p->flags & PKT_IGNORE_CHECKSUM) { |
438 | 0 | return cd->valid; |
439 | 0 | } |
440 | | |
441 | 194 | if (p->level4_comp_csum == -1) |
442 | 194 | p->level4_comp_csum = TCPV6Checksum(p->ip6h->s_ip6_addrs, |
443 | 194 | (uint16_t *)p->tcph, |
444 | 194 | (p->payload_len + |
445 | 194 | TCP_GET_HLEN(p)), |
446 | 194 | p->tcph->th_sum); |
447 | | |
448 | 194 | if (p->level4_comp_csum == 0 && cd->valid == 1) |
449 | 0 | return 1; |
450 | 194 | else if (p->level4_comp_csum != 0 && cd->valid == 0) |
451 | 194 | return 1; |
452 | 0 | else |
453 | 0 | return 0; |
454 | 194 | } |
455 | | |
456 | | /** |
457 | | * \brief Creates a SigMatch for the tcpv6-csum keyword being sent as argument, |
458 | | * and appends it to the Signature(s). Accepts 2 values for the |
459 | | * keyword - "valid" and "invalid", both with and without quotes |
460 | | * |
461 | | * \param de_ctx Pointer to the detection engine context |
462 | | * \param s Pointer to signature for the current Signature being parsed |
463 | | * from the rules |
464 | | * \param csum_str Pointer to the string holding the keyword value |
465 | | * |
466 | | * \retval 0 on success, -1 on failure |
467 | | */ |
468 | | static int DetectTCPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
469 | 768 | { |
470 | 768 | DetectCsumData *cd = NULL; |
471 | 768 | SigMatch *sm = NULL; |
472 | | |
473 | | //printf("DetectCsumSetup: \'%s\'\n", csum_str); |
474 | | |
475 | 768 | sm = SigMatchAlloc(); |
476 | 768 | if (sm == NULL) |
477 | 0 | goto error; |
478 | | |
479 | 768 | sm->type = DETECT_TCPV6_CSUM; |
480 | | |
481 | 768 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
482 | 0 | goto error; |
483 | 768 | memset(cd, 0, sizeof(DetectCsumData)); |
484 | | |
485 | 768 | if (DetectCsumParseArg(csum_str, cd) == 0) |
486 | 17 | goto error; |
487 | | |
488 | 751 | sm->ctx = (SigMatchCtx *)cd; |
489 | | |
490 | 751 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
491 | | |
492 | 751 | return 0; |
493 | | |
494 | 17 | error: |
495 | 17 | if (cd != NULL) DetectTCPV6CsumFree(de_ctx, cd); |
496 | 17 | if (sm != NULL) SCFree(sm); |
497 | | |
498 | 17 | return -1; |
499 | 768 | } |
500 | | |
501 | | static void DetectTCPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
502 | 768 | { |
503 | 768 | DetectCsumData *cd = (DetectCsumData *)ptr; |
504 | | |
505 | 768 | if (cd != NULL) |
506 | 768 | SCFree(cd); |
507 | | |
508 | 768 | return; |
509 | 768 | } |
510 | | |
511 | | /** |
512 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
513 | | * udpv4 checksum, based on whether udpv4-csum option for this rule |
514 | | * has been supplied with "valid" or "invalid" argument |
515 | | * |
516 | | * \param t Pointer to the tv for this detection module instance |
517 | | * \param det_ctx Pointer to the detection engine thread context |
518 | | * \param p Pointer to the Packet currently being matched |
519 | | * \param s Pointer to the Signature, the packet is being currently |
520 | | * matched with |
521 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
522 | | * Signature, the Packet is being currently matched with |
523 | | * |
524 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
525 | | */ |
526 | | static int DetectUDPV4CsumMatch(DetectEngineThreadCtx *det_ctx, |
527 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
528 | 493 | { |
529 | 493 | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
530 | | |
531 | 493 | if (p->ip4h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p) || p->udph->uh_sum == 0) |
532 | 85 | return 0; |
533 | | |
534 | 408 | if (p->flags & PKT_IGNORE_CHECKSUM) { |
535 | 0 | return cd->valid; |
536 | 0 | } |
537 | | |
538 | 408 | if (p->level4_comp_csum == -1) |
539 | 408 | p->level4_comp_csum = UDPV4Checksum(p->ip4h->s_ip_addrs, |
540 | 408 | (uint16_t *)p->udph, |
541 | 408 | (p->payload_len + |
542 | 408 | UDP_HEADER_LEN), |
543 | 408 | p->udph->uh_sum); |
544 | | |
545 | 408 | if (p->level4_comp_csum == 0 && cd->valid == 1) |
546 | 0 | return 1; |
547 | 408 | else if (p->level4_comp_csum != 0 && cd->valid == 0) |
548 | 203 | return 1; |
549 | 205 | else |
550 | 205 | return 0; |
551 | 408 | } |
552 | | |
553 | | /** |
554 | | * \brief Creates a SigMatch for the udpv4-csum keyword being sent as argument, |
555 | | * and appends it to the Signature(s). Accepts 2 values for the |
556 | | * keyword - "valid" and "invalid", both with and without quotes |
557 | | * |
558 | | * \param de_ctx Pointer to the detection engine context |
559 | | * \param s Pointer to signature for the current Signature being parsed |
560 | | * from the rules |
561 | | * \param csum_str Pointer to the string holding the keyword value |
562 | | * |
563 | | * \retval 0 on success, -1 on failure |
564 | | */ |
565 | | static int DetectUDPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
566 | 549 | { |
567 | 549 | DetectCsumData *cd = NULL; |
568 | 549 | SigMatch *sm = NULL; |
569 | | |
570 | | //printf("DetectCsumSetup: \'%s\'\n", csum_str); |
571 | | |
572 | 549 | sm = SigMatchAlloc(); |
573 | 549 | if (sm == NULL) |
574 | 0 | goto error; |
575 | | |
576 | 549 | sm->type = DETECT_UDPV4_CSUM; |
577 | | |
578 | 549 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
579 | 0 | goto error; |
580 | 549 | memset(cd, 0, sizeof(DetectCsumData)); |
581 | | |
582 | 549 | if (DetectCsumParseArg(csum_str, cd) == 0) |
583 | 19 | goto error; |
584 | | |
585 | 530 | sm->ctx = (SigMatchCtx *)cd; |
586 | | |
587 | 530 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
588 | | |
589 | 530 | return 0; |
590 | | |
591 | 19 | error: |
592 | 19 | if (cd != NULL) DetectUDPV4CsumFree(de_ctx, cd); |
593 | 19 | if (sm != NULL) SCFree(sm); |
594 | | |
595 | 19 | return -1; |
596 | 549 | } |
597 | | |
598 | | static void DetectUDPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
599 | 549 | { |
600 | 549 | DetectCsumData *cd = (DetectCsumData *)ptr; |
601 | | |
602 | 549 | if (cd != NULL) |
603 | 549 | SCFree(cd); |
604 | | |
605 | 549 | return; |
606 | 549 | } |
607 | | |
608 | | /** |
609 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
610 | | * udpv6 checksum, based on whether udpv6-csum option for this rule |
611 | | * has been supplied with "valid" or "invalid" argument |
612 | | * |
613 | | * \param t Pointer to the tv for this detection module instance |
614 | | * \param det_ctx Pointer to the detection engine thread context |
615 | | * \param p Pointer to the Packet currently being matched |
616 | | * \param s Pointer to the Signature, the packet is being currently |
617 | | * matched with |
618 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
619 | | * Signature, the Packet is being currently matched with |
620 | | * |
621 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
622 | | */ |
623 | | static int DetectUDPV6CsumMatch(DetectEngineThreadCtx *det_ctx, |
624 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
625 | 245 | { |
626 | 245 | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
627 | | |
628 | 245 | if (p->ip6h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p)) |
629 | 213 | return 0; |
630 | | |
631 | 32 | if (p->flags & PKT_IGNORE_CHECKSUM) { |
632 | 0 | return cd->valid; |
633 | 0 | } |
634 | | |
635 | 32 | if (p->level4_comp_csum == -1) |
636 | 32 | p->level4_comp_csum = UDPV6Checksum(p->ip6h->s_ip6_addrs, |
637 | 32 | (uint16_t *)p->udph, |
638 | 32 | (p->payload_len + |
639 | 32 | UDP_HEADER_LEN), |
640 | 32 | p->udph->uh_sum); |
641 | | |
642 | 32 | if (p->level4_comp_csum == 0 && cd->valid == 1) |
643 | 0 | return 1; |
644 | 32 | else if (p->level4_comp_csum != 0 && cd->valid == 0) |
645 | 0 | return 1; |
646 | 32 | else |
647 | 32 | return 0; |
648 | 32 | } |
649 | | |
650 | | /** |
651 | | * \brief Creates a SigMatch for the udpv6-csum keyword being sent as argument, |
652 | | * and appends it to the Signature(s). Accepts 2 values for the |
653 | | * keyword - "valid" and "invalid", both with and without quotes |
654 | | * |
655 | | * \param de_ctx Pointer to the detection engine context |
656 | | * \param s Pointer to signature for the current Signature being parsed |
657 | | * from the rules |
658 | | * \param csum_str Pointer to the string holding the keyword value |
659 | | * |
660 | | * \retval 0 on success, -1 on failure |
661 | | */ |
662 | | static int DetectUDPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
663 | 460 | { |
664 | 460 | DetectCsumData *cd = NULL; |
665 | 460 | SigMatch *sm = NULL; |
666 | | |
667 | | //printf("DetectCsumSetup: \'%s\'\n", csum_str); |
668 | | |
669 | 460 | sm = SigMatchAlloc(); |
670 | 460 | if (sm == NULL) |
671 | 0 | goto error; |
672 | | |
673 | 460 | sm->type = DETECT_UDPV6_CSUM; |
674 | | |
675 | 460 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
676 | 0 | goto error; |
677 | 460 | memset(cd, 0, sizeof(DetectCsumData)); |
678 | | |
679 | 460 | if (DetectCsumParseArg(csum_str, cd) == 0) |
680 | 86 | goto error; |
681 | | |
682 | 374 | sm->ctx = (void *)cd; |
683 | | |
684 | 374 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
685 | | |
686 | 374 | return 0; |
687 | | |
688 | 86 | error: |
689 | 86 | if (cd != NULL) DetectUDPV6CsumFree(de_ctx, cd); |
690 | 86 | if (sm != NULL) SCFree(sm); |
691 | | |
692 | 86 | return -1; |
693 | 460 | } |
694 | | |
695 | | static void DetectUDPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
696 | 460 | { |
697 | 460 | DetectCsumData *cd = (DetectCsumData *)ptr; |
698 | | |
699 | 460 | if (cd != NULL) |
700 | 460 | SCFree(cd); |
701 | | |
702 | 460 | return; |
703 | 460 | } |
704 | | |
705 | | /** |
706 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
707 | | * icmpv4 checksum, based on whether icmpv4-csum option for this rule |
708 | | * has been supplied with "valid" or "invalid" argument |
709 | | * |
710 | | * \param t Pointer to the tv for this detection module instance |
711 | | * \param det_ctx Pointer to the detection engine thread context |
712 | | * \param p Pointer to the Packet currently being matched |
713 | | * \param s Pointer to the Signature, the packet is being currently |
714 | | * matched with |
715 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
716 | | * Signature, the Packet is being currently matched with |
717 | | * |
718 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
719 | | */ |
720 | | static int DetectICMPV4CsumMatch(DetectEngineThreadCtx *det_ctx, |
721 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
722 | 83 | { |
723 | 83 | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
724 | | |
725 | 83 | if (p->ip4h == NULL || p->icmpv4h == NULL || p->proto != IPPROTO_ICMP || PKT_IS_PSEUDOPKT(p)) |
726 | 80 | return 0; |
727 | | |
728 | 3 | if (p->flags & PKT_IGNORE_CHECKSUM) { |
729 | 0 | return cd->valid; |
730 | 0 | } |
731 | | |
732 | 3 | if (p->level4_comp_csum == -1) |
733 | 3 | p->level4_comp_csum = ICMPV4CalculateChecksum((uint16_t *)p->icmpv4h, |
734 | 3 | SCNtohs(IPV4_GET_RAW_IPLEN(p->ip4h)) - |
735 | 3 | IPV4_GET_RAW_HLEN(p->ip4h) * 4); |
736 | | |
737 | 3 | if (p->level4_comp_csum == p->icmpv4h->checksum && cd->valid == 1) |
738 | 0 | return 1; |
739 | 3 | else if (p->level4_comp_csum != p->icmpv4h->checksum && cd->valid == 0) |
740 | 3 | return 1; |
741 | 0 | else |
742 | 0 | return 0; |
743 | 3 | } |
744 | | |
745 | | /** |
746 | | * \brief Creates a SigMatch for the icmpv4-csum keyword being sent as argument, |
747 | | * and appends it to the Signature(s). Accepts 2 values for the |
748 | | * keyword - "valid" and "invalid", both with and without quotes |
749 | | * |
750 | | * \param de_ctx Pointer to the detection engine context |
751 | | * \param s Pointer to signature for the current Signature being parsed |
752 | | * from the rules |
753 | | * \param csum_str Pointer to the string holding the keyword value |
754 | | * |
755 | | * \retval 0 on success, -1 on failure |
756 | | */ |
757 | | static int DetectICMPV4CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
758 | 495 | { |
759 | 495 | DetectCsumData *cd = NULL; |
760 | 495 | SigMatch *sm = NULL; |
761 | | |
762 | | //printf("DetectCsumSetup: \'%s\'\n", csum_str); |
763 | | |
764 | 495 | sm = SigMatchAlloc(); |
765 | 495 | if (sm == NULL) |
766 | 0 | goto error; |
767 | | |
768 | 495 | sm->type = DETECT_ICMPV4_CSUM; |
769 | | |
770 | 495 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
771 | 0 | goto error; |
772 | 495 | memset(cd, 0, sizeof(DetectCsumData)); |
773 | | |
774 | 495 | if (DetectCsumParseArg(csum_str, cd) == 0) |
775 | 16 | goto error; |
776 | | |
777 | 479 | sm->ctx = (SigMatchCtx *)cd; |
778 | | |
779 | 479 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
780 | | |
781 | 479 | return 0; |
782 | | |
783 | 16 | error: |
784 | 16 | if (cd != NULL) DetectICMPV4CsumFree(de_ctx, cd); |
785 | 16 | if (sm != NULL) SCFree(sm); |
786 | | |
787 | 16 | return -1; |
788 | 495 | } |
789 | | |
790 | | static void DetectICMPV4CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
791 | 495 | { |
792 | 495 | DetectCsumData *cd = (DetectCsumData *)ptr; |
793 | | |
794 | 495 | if (cd != NULL) |
795 | 495 | SCFree(cd); |
796 | | |
797 | 495 | return; |
798 | 495 | } |
799 | | |
800 | | /** |
801 | | * \brief Checks if the packet sent as the argument, has a valid or invalid |
802 | | * icmpv6 checksum, based on whether icmpv6-csum option for this rule |
803 | | * has been supplied with "valid" or "invalid" argument |
804 | | * |
805 | | * \param t Pointer to the tv for this detection module instance |
806 | | * \param det_ctx Pointer to the detection engine thread context |
807 | | * \param p Pointer to the Packet currently being matched |
808 | | * \param s Pointer to the Signature, the packet is being currently |
809 | | * matched with |
810 | | * \param m Pointer to the keyword_structure(SigMatch) from the above |
811 | | * Signature, the Packet is being currently matched with |
812 | | * |
813 | | * \retval 1 if the Packet contents match the keyword option; 0 otherwise |
814 | | */ |
815 | | static int DetectICMPV6CsumMatch(DetectEngineThreadCtx *det_ctx, |
816 | | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
817 | 14 | { |
818 | 14 | const DetectCsumData *cd = (const DetectCsumData *)ctx; |
819 | | |
820 | 14 | if (p->ip6h == NULL || p->icmpv6h == NULL || p->proto != IPPROTO_ICMPV6 || PKT_IS_PSEUDOPKT(p) || |
821 | 12 | (GET_PKT_LEN(p) - ((uint8_t *)p->icmpv6h - GET_PKT_DATA(p))) <= 0) { |
822 | 2 | return 0; |
823 | 2 | } |
824 | | |
825 | 12 | if (p->flags & PKT_IGNORE_CHECKSUM) { |
826 | 0 | return cd->valid; |
827 | 0 | } |
828 | | |
829 | 12 | if (p->level4_comp_csum == -1) { |
830 | 12 | uint16_t len = IPV6_GET_RAW_PLEN(p->ip6h) - |
831 | 12 | (uint16_t)((uint8_t *)p->icmpv6h - (uint8_t *)p->ip6h - IPV6_HEADER_LEN); |
832 | 12 | p->level4_comp_csum = ICMPV6CalculateChecksum(p->ip6h->s_ip6_addrs, |
833 | 12 | (uint16_t *)p->icmpv6h, |
834 | 12 | len); |
835 | 12 | } |
836 | | |
837 | 12 | if (p->level4_comp_csum == p->icmpv6h->csum && cd->valid == 1) |
838 | 0 | return 1; |
839 | 12 | else if (p->level4_comp_csum != p->icmpv6h->csum && cd->valid == 0) |
840 | 1 | return 1; |
841 | 11 | else |
842 | 11 | return 0; |
843 | 12 | } |
844 | | |
845 | | /** |
846 | | * \brief Creates a SigMatch for the icmpv6-csum keyword being sent as argument, |
847 | | * and appends it to the Signature(s). Accepts 2 values for the |
848 | | * keyword - "valid" and "invalid", both with and without quotes |
849 | | * |
850 | | * \param de_ctx Pointer to the detection engine context |
851 | | * \param s Pointer to signature for the current Signature being parsed |
852 | | * from the rules |
853 | | * \param csum_str Pointer to the string holding the keyword value |
854 | | * |
855 | | * \retval 0 on success, -1 on failure |
856 | | */ |
857 | | static int DetectICMPV6CsumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *csum_str) |
858 | 606 | { |
859 | 606 | DetectCsumData *cd = NULL; |
860 | 606 | SigMatch *sm = NULL; |
861 | | |
862 | 606 | sm = SigMatchAlloc(); |
863 | 606 | if (sm == NULL) |
864 | 0 | goto error; |
865 | | |
866 | 606 | sm->type = DETECT_ICMPV6_CSUM; |
867 | | |
868 | 606 | if ( (cd = SCMalloc(sizeof(DetectCsumData))) == NULL) |
869 | 0 | goto error; |
870 | 606 | memset(cd, 0, sizeof(DetectCsumData)); |
871 | | |
872 | 606 | if (DetectCsumParseArg(csum_str, cd) == 0) |
873 | 7 | goto error; |
874 | | |
875 | 599 | sm->ctx = (SigMatchCtx *)cd; |
876 | | |
877 | 599 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
878 | | |
879 | 599 | return 0; |
880 | | |
881 | 7 | error: |
882 | 7 | if (cd != NULL) DetectICMPV6CsumFree(de_ctx, cd); |
883 | 7 | if (sm != NULL) SCFree(sm); |
884 | | |
885 | 7 | return -1; |
886 | 606 | } |
887 | | |
888 | | static void DetectICMPV6CsumFree(DetectEngineCtx *de_ctx, void *ptr) |
889 | 606 | { |
890 | 606 | DetectCsumData *cd = (DetectCsumData *)ptr; |
891 | | |
892 | 606 | if (cd != NULL) |
893 | 606 | SCFree(cd); |
894 | | |
895 | 606 | return; |
896 | 606 | } |
897 | | |
898 | | /* ---------------------------------- Unit Tests --------------------------- */ |
899 | | |
900 | | #ifdef UNITTESTS |
901 | | #include "util-unittest-helper.h" |
902 | | #include "detect-engine.h" |
903 | | #include "detect-engine-alert.h" |
904 | | #include "packet.h" |
905 | | |
906 | | #define mystr(s) #s |
907 | | #define TEST1(kwstr) {\ |
908 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit();\ |
909 | | FAIL_IF_NULL(de_ctx);\ |
910 | | de_ctx->flags = DE_QUIET;\ |
911 | | \ |
912 | | Signature *s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:valid; sid:1;)");\ |
913 | | FAIL_IF_NULL(s);\ |
914 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:invalid; sid:2;)");\ |
915 | | FAIL_IF_NULL(s);\ |
916 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:vaLid; sid:3;)");\ |
917 | | FAIL_IF_NULL(s);\ |
918 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:VALID; sid:4;)");\ |
919 | | FAIL_IF_NULL(s);\ |
920 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:iNvaLid; sid:5;)");\ |
921 | | FAIL_IF_NULL(s);\ |
922 | | DetectEngineCtxFree(de_ctx);\ |
923 | | } |
924 | | |
925 | | |
926 | | static int DetectCsumValidArgsTestParse01(void) |
927 | | { |
928 | | TEST1(ipv4); |
929 | | TEST1(tcpv4); |
930 | | TEST1(tcpv6); |
931 | | TEST1(udpv4); |
932 | | TEST1(udpv6); |
933 | | TEST1(icmpv4); |
934 | | TEST1(icmpv6); |
935 | | PASS; |
936 | | } |
937 | | #undef TEST1 |
938 | | |
939 | | #define TEST2(kwstr) \ |
940 | | { \ |
941 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \ |
942 | | FAIL_IF_NULL(de_ctx); \ |
943 | | Signature *s = DetectEngineAppendSig( \ |
944 | | de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:xxxx; sid:1;)"); \ |
945 | | FAIL_IF(s); \ |
946 | | s = DetectEngineAppendSig( \ |
947 | | de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:xxxxxxxx; sid:2;)"); \ |
948 | | FAIL_IF(s); \ |
949 | | s = DetectEngineAppendSig( \ |
950 | | de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:xxxxxx; sid:3;)"); \ |
951 | | FAIL_IF(s); \ |
952 | | s = DetectEngineAppendSig( \ |
953 | | de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:XXXXXX; sid:4;)"); \ |
954 | | FAIL_IF(s); \ |
955 | | s = DetectEngineAppendSig( \ |
956 | | de_ctx, "alert ip any any -> any any (" mystr(kwstr) "-csum:XxXxXxX; sid:5;)"); \ |
957 | | FAIL_IF(s); \ |
958 | | DetectEngineCtxFree(de_ctx); \ |
959 | | } |
960 | | |
961 | | static int DetectCsumInvalidArgsTestParse02(void) |
962 | | { |
963 | | TEST2(ipv4); |
964 | | TEST2(tcpv4); |
965 | | TEST2(tcpv6); |
966 | | TEST2(udpv4); |
967 | | TEST2(udpv6); |
968 | | TEST2(icmpv4); |
969 | | TEST2(icmpv6); |
970 | | PASS; |
971 | | } |
972 | | #undef TEST2 |
973 | | |
974 | | #define TEST3(kwstr, kwtype) { \ |
975 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit();\ |
976 | | FAIL_IF_NULL(de_ctx);\ |
977 | | Signature *s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:valid; sid:1;)");\ |
978 | | FAIL_IF_NULL(s);\ |
979 | | SigMatch *sm = DetectGetLastSMFromLists(s, (kwtype), -1);\ |
980 | | FAIL_IF_NULL(sm);\ |
981 | | FAIL_IF_NULL(sm->ctx);\ |
982 | | FAIL_IF_NOT(((DetectCsumData *)sm->ctx)->valid == 1);\ |
983 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any ("mystr(kwstr)"-csum:INVALID; sid:2;)");\ |
984 | | FAIL_IF_NULL(s);\ |
985 | | sm = DetectGetLastSMFromLists(s, (kwtype), -1);\ |
986 | | FAIL_IF_NULL(sm);\ |
987 | | FAIL_IF_NULL(sm->ctx);\ |
988 | | FAIL_IF_NOT(((DetectCsumData *)sm->ctx)->valid == 0);\ |
989 | | DetectEngineCtxFree(de_ctx);\ |
990 | | } |
991 | | |
992 | | static int DetectCsumValidArgsTestParse03(void) |
993 | | { |
994 | | TEST3(ipv4, DETECT_IPV4_CSUM); |
995 | | TEST3(tcpv4, DETECT_TCPV4_CSUM); |
996 | | TEST3(tcpv6, DETECT_TCPV6_CSUM); |
997 | | TEST3(udpv4, DETECT_UDPV4_CSUM); |
998 | | TEST3(udpv6, DETECT_UDPV6_CSUM); |
999 | | TEST3(icmpv4, DETECT_ICMPV4_CSUM); |
1000 | | TEST3(icmpv6, DETECT_ICMPV6_CSUM); |
1001 | | PASS; |
1002 | | } |
1003 | | #undef TEST3 |
1004 | | #undef mystr |
1005 | | |
1006 | | #include "stream-tcp.h" |
1007 | | |
1008 | | static int DetectCsumICMPV6Test01(void) |
1009 | | { |
1010 | | DetectEngineCtx *de_ctx = NULL; |
1011 | | Signature *s = NULL; |
1012 | | ThreadVars tv; |
1013 | | DetectEngineThreadCtx *det_ctx = NULL; |
1014 | | DecodeThreadVars dtv; |
1015 | | |
1016 | | Packet *p = PacketGetFromAlloc(); |
1017 | | FAIL_IF_NULL(p); |
1018 | | |
1019 | | uint8_t pkt[] = { |
1020 | | 0x00, 0x30, 0x18, 0xa8, 0x7c, 0x23, 0x2c, 0x41, |
1021 | | 0x38, 0xa7, 0xea, 0xeb, 0x86, 0xdd, 0x60, 0x00, |
1022 | | 0x00, 0x00, 0x00, 0x40, 0x3c, 0x40, 0xad, 0xa1, |
1023 | | 0x09, 0x80, 0x00, 0x01, 0xd6, 0xf3, 0x20, 0x01, |
1024 | | 0xf4, 0xbe, 0xea, 0x3c, 0x00, 0x01, 0x00, 0x00, |
1025 | | 0x00, 0x00, 0x32, 0xb2, 0x00, 0x01, 0x32, 0xb2, |
1026 | | 0x09, 0x80, 0x20, 0x01, 0x00, 0x00, 0x3c, 0x00, |
1027 | | 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, |
1028 | | 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, |
1029 | | 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, |
1030 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, |
1031 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, |
1032 | | 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, |
1033 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, |
1034 | | 0x63, 0xc2, 0x00, 0x00, 0x00, 0x00 }; |
1035 | | |
1036 | | PacketCopyData(p, pkt, sizeof(pkt)); |
1037 | | |
1038 | | memset(&tv, 0, sizeof(tv)); |
1039 | | memset(&dtv, 0, sizeof(dtv)); |
1040 | | |
1041 | | StreamTcpInitConfig(true); |
1042 | | FlowInitConfig(FLOW_QUIET); |
1043 | | |
1044 | | de_ctx = DetectEngineCtxInit(); |
1045 | | FAIL_IF_NULL(de_ctx); |
1046 | | de_ctx->mpm_matcher = mpm_default_matcher; |
1047 | | de_ctx->flags |= DE_QUIET; |
1048 | | |
1049 | | s = de_ctx->sig_list = SigInit(de_ctx, "alert ip any any -> any any " |
1050 | | "(icmpv6-csum:valid; sid:1;)"); |
1051 | | FAIL_IF_NULL(s); |
1052 | | SigGroupBuild(de_ctx); |
1053 | | |
1054 | | DecodeEthernet(&tv, &dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p)); |
1055 | | |
1056 | | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); |
1057 | | |
1058 | | SigMatchSignatures(&tv, de_ctx, det_ctx, p); |
1059 | | |
1060 | | FAIL_IF(!PacketAlertCheck(p, 1)); |
1061 | | |
1062 | | DetectEngineThreadCtxDeinit(&tv, det_ctx); |
1063 | | DetectEngineCtxFree(de_ctx); |
1064 | | |
1065 | | StreamTcpFreeConfig(true); |
1066 | | PacketRecycle(p); |
1067 | | FlowShutdown(); |
1068 | | SCFree(p); |
1069 | | PASS; |
1070 | | } |
1071 | | |
1072 | | static void DetectCsumRegisterTests(void) |
1073 | | { |
1074 | | UtRegisterTest("DetectCsumValidArgsTestParse01", |
1075 | | DetectCsumValidArgsTestParse01); |
1076 | | UtRegisterTest("DetectCsumInvalidArgsTestParse02", |
1077 | | DetectCsumInvalidArgsTestParse02); |
1078 | | UtRegisterTest("DetectCsumValidArgsTestParse03", |
1079 | | DetectCsumValidArgsTestParse03); |
1080 | | |
1081 | | UtRegisterTest("DetectCsumICMPV6Test01", |
1082 | | DetectCsumICMPV6Test01); |
1083 | | } |
1084 | | #endif /* UNITTESTS */ |