]>
Commit | Line | Data |
---|---|---|
f10dd603 VJ |
1 | /* Copyright (C) 2013 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 | * \ingroup dnslayer | |
20 | * | |
21 | * @{ | |
22 | */ | |
23 | ||
24 | ||
25 | /** | |
26 | * \file | |
27 | * | |
28 | * \author Victor Julien <victor@inliniac.net> | |
29 | */ | |
30 | ||
31 | #include "suricata-common.h" | |
32 | #include "threads.h" | |
33 | #include "debug.h" | |
34 | #include "decode.h" | |
35 | #include "detect.h" | |
36 | ||
37 | #include "detect-parse.h" | |
38 | #include "detect-engine.h" | |
39 | #include "detect-engine-mpm.h" | |
40 | #include "detect-content.h" | |
41 | #include "detect-pcre.h" | |
42 | ||
43 | #include "flow.h" | |
e567e122 | 44 | #include "flow-util.h" |
f10dd603 VJ |
45 | #include "flow-var.h" |
46 | ||
47 | #include "util-debug.h" | |
48 | #include "util-unittest.h" | |
49 | #include "util-spm.h" | |
50 | #include "util-print.h" | |
51 | ||
429c6388 AS |
52 | #include "stream-tcp.h" |
53 | ||
f10dd603 | 54 | #include "app-layer.h" |
e567e122 | 55 | #include "app-layer-dns-common.h" |
f10dd603 | 56 | #include "detect-dns-query.h" |
57ae3c43 | 57 | #include "detect-engine-dns.h" |
f10dd603 | 58 | |
e567e122 VJ |
59 | #include "util-unittest-helper.h" |
60 | ||
f10dd603 | 61 | static int DetectDnsQuerySetup (DetectEngineCtx *, Signature *, char *); |
e567e122 | 62 | static void DetectDnsQueryRegisterTests(void); |
f10dd603 VJ |
63 | |
64 | /** | |
57ae3c43 | 65 | * \brief Registration function for keyword: dns_query |
f10dd603 | 66 | */ |
8f1d7503 KS |
67 | void DetectDnsQueryRegister (void) |
68 | { | |
f10dd603 VJ |
69 | sigmatch_table[DETECT_AL_DNS_QUERY].name = "dns_query"; |
70 | sigmatch_table[DETECT_AL_DNS_QUERY].desc = "content modifier to match specifically and only on the DNS query-buffer"; | |
71 | sigmatch_table[DETECT_AL_DNS_QUERY].Match = NULL; | |
72 | sigmatch_table[DETECT_AL_DNS_QUERY].AppLayerMatch = NULL; | |
f10dd603 VJ |
73 | sigmatch_table[DETECT_AL_DNS_QUERY].Setup = DetectDnsQuerySetup; |
74 | sigmatch_table[DETECT_AL_DNS_QUERY].Free = NULL; | |
e567e122 | 75 | sigmatch_table[DETECT_AL_DNS_QUERY].RegisterTests = DetectDnsQueryRegisterTests; |
f10dd603 | 76 | |
02529b13 | 77 | sigmatch_table[DETECT_AL_DNS_QUERY].flags |= SIGMATCH_NOOPT; |
f10dd603 | 78 | sigmatch_table[DETECT_AL_DNS_QUERY].flags |= SIGMATCH_PAYLOAD; |
57ae3c43 VJ |
79 | |
80 | DetectMpmAppLayerRegister("dns_query", SIG_FLAG_TOSERVER, | |
960461f4 | 81 | DETECT_SM_LIST_DNSQUERYNAME_MATCH, 2, |
57ae3c43 VJ |
82 | PrefilterTxDnsQueryRegister); |
83 | ||
2db094ab VJ |
84 | DetectAppLayerInspectEngineRegister(ALPROTO_DNS, SIG_FLAG_TOSERVER, |
85 | DETECT_SM_LIST_DNSQUERYNAME_MATCH, | |
86 | DetectEngineInspectDnsQueryName); | |
87 | ||
88 | /* register these generic engines from here for now */ | |
89 | DetectAppLayerInspectEngineRegister(ALPROTO_DNS, SIG_FLAG_TOSERVER, | |
90 | DETECT_SM_LIST_DNSREQUEST_MATCH, | |
91 | DetectEngineInspectDnsRequest); | |
92 | DetectAppLayerInspectEngineRegister(ALPROTO_DNS, SIG_FLAG_TOCLIENT, | |
93 | DETECT_SM_LIST_DNSRESPONSE_MATCH, | |
94 | DetectEngineInspectDnsResponse); | |
f10dd603 VJ |
95 | } |
96 | ||
97 | ||
98 | /** | |
99 | * \brief this function setups the dns_query modifier keyword used in the rule | |
100 | * | |
101 | * \param de_ctx Pointer to the Detection Engine Context | |
102 | * \param s Pointer to the Signature to which the current keyword belongs | |
103 | * \param str Should hold an empty string always | |
104 | * | |
105 | * \retval 0 On success | |
106 | * \retval -1 On failure | |
107 | */ | |
108 | ||
109 | static int DetectDnsQuerySetup(DetectEngineCtx *de_ctx, Signature *s, char *str) | |
110 | { | |
2c8e8c25 | 111 | s->list = DETECT_SM_LIST_DNSQUERYNAME_MATCH; |
d0c5f512 | 112 | s->alproto = ALPROTO_DNS; |
f353fb63 | 113 | return 0; |
f10dd603 | 114 | } |
e567e122 VJ |
115 | |
116 | #ifdef UNITTESTS | |
117 | /** \test simple google.com query matching */ | |
8f1d7503 KS |
118 | static int DetectDnsQueryTest01(void) |
119 | { | |
e567e122 VJ |
120 | /* google.com */ |
121 | uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
122 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
123 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
124 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
125 | 0x00, 0x10, 0x00, 0x01, }; | |
126 | int result = 0; | |
127 | Flow f; | |
128 | DNSState *dns_state = NULL; | |
129 | Packet *p = NULL; | |
130 | Signature *s = NULL; | |
131 | ThreadVars tv; | |
132 | DetectEngineThreadCtx *det_ctx = NULL; | |
8dbf7a0d | 133 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
e567e122 VJ |
134 | |
135 | memset(&tv, 0, sizeof(ThreadVars)); | |
136 | memset(&f, 0, sizeof(Flow)); | |
137 | ||
6f8cfd99 AS |
138 | p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP, |
139 | "192.168.1.5", "192.168.1.1", | |
140 | 41424, 53); | |
e567e122 VJ |
141 | |
142 | FLOW_INITIALIZE(&f); | |
143 | f.flags |= FLOW_IPV4; | |
144 | f.proto = IPPROTO_UDP; | |
a77b9b36 | 145 | f.protomap = FlowGetProtoMapping(f.proto); |
e567e122 VJ |
146 | |
147 | p->flow = &f; | |
148 | p->flags |= PKT_HAS_FLOW; | |
149 | p->flowflags |= FLOW_PKT_TOSERVER; | |
429c6388 | 150 | f.alproto = ALPROTO_DNS; |
e567e122 VJ |
151 | |
152 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
153 | if (de_ctx == NULL) { | |
154 | goto end; | |
155 | } | |
e6044aaf | 156 | de_ctx->mpm_matcher = mpm_default_matcher; |
e567e122 VJ |
157 | de_ctx->flags |= DE_QUIET; |
158 | ||
f592c481 | 159 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
ddde572f AS |
160 | "(msg:\"Test dns_query option\"; " |
161 | "dns_query; content:\"google\"; nocase; sid:1;)"); | |
e567e122 VJ |
162 | if (s == NULL) { |
163 | goto end; | |
164 | } | |
165 | ||
166 | SigGroupBuild(de_ctx); | |
167 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
168 | ||
6530c3d0 | 169 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
170 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
171 | STREAM_TOSERVER, buf, sizeof(buf)); | |
e567e122 VJ |
172 | if (r != 0) { |
173 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 174 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
175 | goto end; |
176 | } | |
6530c3d0 | 177 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
178 | |
179 | dns_state = f.alstate; | |
180 | if (dns_state == NULL) { | |
181 | printf("no dns state: "); | |
182 | goto end; | |
183 | } | |
184 | ||
185 | /* do detect */ | |
186 | SigMatchSignatures(&tv, de_ctx, det_ctx, p); | |
187 | ||
188 | if (!(PacketAlertCheck(p, 1))) { | |
189 | printf("sig 1 didn't alert, but it should have: "); | |
190 | goto end; | |
191 | } | |
192 | ||
193 | result = 1; | |
194 | ||
195 | end: | |
429c6388 | 196 | if (alp_tctx != NULL) |
fdefb65b | 197 | AppLayerParserThreadCtxFree(alp_tctx); |
e567e122 VJ |
198 | if (det_ctx != NULL) |
199 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
200 | if (de_ctx != NULL) | |
201 | SigGroupCleanup(de_ctx); | |
202 | if (de_ctx != NULL) | |
203 | DetectEngineCtxFree(de_ctx); | |
204 | ||
205 | FLOW_DESTROY(&f); | |
206 | UTHFreePacket(p); | |
207 | return result; | |
208 | } | |
209 | ||
210 | /** \test multi tx google.(com|net) query matching */ | |
8f1d7503 KS |
211 | static int DetectDnsQueryTest02(void) |
212 | { | |
e567e122 VJ |
213 | /* google.com */ |
214 | uint8_t buf1[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
215 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
216 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
217 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
218 | 0x00, 0x01, 0x00, 0x01, }; | |
219 | ||
220 | uint8_t buf2[] = { 0x10, 0x32, /* tx id */ | |
221 | 0x81, 0x80, /* flags: resp, recursion desired, recusion available */ | |
222 | 0x00, 0x01, /* 1 query */ | |
223 | 0x00, 0x01, /* 1 answer */ | |
224 | 0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */ | |
225 | /* query record */ | |
226 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */ | |
227 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */ | |
228 | 0x00, 0x01, 0x00, 0x01, /* type a, class in */ | |
229 | /* answer */ | |
230 | 0xc0, 0x0c, /* ref to name in query above */ | |
231 | 0x00, 0x01, 0x00, 0x01, /* type a, class in */ | |
232 | 0x00, 0x01, 0x40, 0xef, /* ttl */ | |
233 | 0x00, 0x04, /* data len */ | |
234 | 0x01, 0x02, 0x03, 0x04 }; /* addr */ | |
235 | ||
236 | /* google.net */ | |
237 | uint8_t buf3[] = { 0x11, 0x33, 0x01, 0x00, 0x00, 0x01, | |
238 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
239 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
240 | 0x65, 0x03, 0x6E, 0x65, 0x74, 0x00, | |
241 | 0x00, 0x10, 0x00, 0x01, }; | |
242 | int result = 0; | |
243 | Flow f; | |
244 | DNSState *dns_state = NULL; | |
245 | Packet *p1 = NULL, *p2 = NULL, *p3 = NULL; | |
246 | Signature *s = NULL; | |
247 | ThreadVars tv; | |
248 | DetectEngineThreadCtx *det_ctx = NULL; | |
8dbf7a0d | 249 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
e567e122 VJ |
250 | |
251 | memset(&tv, 0, sizeof(ThreadVars)); | |
252 | memset(&f, 0, sizeof(Flow)); | |
253 | ||
6f8cfd99 AS |
254 | p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, |
255 | "192.168.1.5", "192.168.1.1", | |
256 | 41424, 53); | |
257 | p2 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, | |
258 | "192.168.1.5", "192.168.1.1", | |
259 | 41424, 53); | |
260 | p3 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, | |
261 | "192.168.1.5", "192.168.1.1", | |
262 | 41424, 53); | |
e567e122 VJ |
263 | |
264 | FLOW_INITIALIZE(&f); | |
265 | f.flags |= FLOW_IPV4; | |
266 | f.proto = IPPROTO_UDP; | |
a77b9b36 | 267 | f.protomap = FlowGetProtoMapping(f.proto); |
429c6388 | 268 | f.alproto = ALPROTO_DNS; |
e567e122 VJ |
269 | |
270 | p1->flow = &f; | |
271 | p1->flags |= PKT_HAS_FLOW; | |
272 | p1->flowflags |= FLOW_PKT_TOSERVER; | |
273 | p1->pcap_cnt = 1; | |
274 | ||
275 | p2->flow = &f; | |
276 | p2->flags |= PKT_HAS_FLOW; | |
277 | p2->flowflags |= FLOW_PKT_TOCLIENT; | |
278 | p2->pcap_cnt = 2; | |
279 | ||
280 | p3->flow = &f; | |
281 | p3->flags |= PKT_HAS_FLOW; | |
282 | p3->flowflags |= FLOW_PKT_TOSERVER; | |
283 | p3->pcap_cnt = 3; | |
284 | ||
285 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
286 | if (de_ctx == NULL) { | |
287 | goto end; | |
288 | } | |
e6044aaf | 289 | de_ctx->mpm_matcher = mpm_default_matcher; |
e567e122 VJ |
290 | de_ctx->flags |= DE_QUIET; |
291 | ||
f592c481 | 292 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
429c6388 AS |
293 | "(msg:\"Test dns_query option\"; " |
294 | "dns_query; content:\"google.com\"; nocase; sid:1;)"); | |
e567e122 VJ |
295 | if (s == NULL) { |
296 | goto end; | |
297 | } | |
f592c481 | 298 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
429c6388 AS |
299 | "(msg:\"Test dns_query option\"; " |
300 | "dns_query; content:\"google.net\"; nocase; sid:2;)"); | |
e567e122 VJ |
301 | if (s == NULL) { |
302 | goto end; | |
303 | } | |
304 | ||
305 | SigGroupBuild(de_ctx); | |
306 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
307 | ||
6530c3d0 | 308 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
309 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
310 | STREAM_TOSERVER, buf1, sizeof(buf1)); | |
e567e122 VJ |
311 | if (r != 0) { |
312 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 313 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
314 | goto end; |
315 | } | |
6530c3d0 | 316 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
317 | |
318 | dns_state = f.alstate; | |
319 | if (dns_state == NULL) { | |
320 | printf("no dns state: "); | |
321 | goto end; | |
322 | } | |
323 | ||
324 | /* do detect */ | |
325 | SigMatchSignatures(&tv, de_ctx, det_ctx, p1); | |
326 | ||
327 | if (!(PacketAlertCheck(p1, 1))) { | |
328 | printf("(p1) sig 1 didn't alert, but it should have: "); | |
329 | goto end; | |
330 | } | |
331 | if (PacketAlertCheck(p1, 2)) { | |
332 | printf("(p1) sig 2 did alert, but it should not have: "); | |
333 | goto end; | |
334 | } | |
335 | ||
6530c3d0 | 336 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
337 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT, |
338 | buf2, sizeof(buf2)); | |
e567e122 VJ |
339 | if (r != 0) { |
340 | printf("toserver client 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 341 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
342 | goto end; |
343 | } | |
6530c3d0 | 344 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
345 | |
346 | /* do detect */ | |
347 | SigMatchSignatures(&tv, de_ctx, det_ctx, p2); | |
348 | ||
349 | if (PacketAlertCheck(p2, 1)) { | |
350 | printf("(p2) sig 1 alerted, but it should not have: "); | |
351 | goto end; | |
352 | } | |
353 | if (PacketAlertCheck(p2, 2)) { | |
354 | printf("(p2) sig 2 alerted, but it should not have: "); | |
355 | goto end; | |
356 | } | |
357 | ||
6530c3d0 | 358 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
359 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER, |
360 | buf3, sizeof(buf3)); | |
e567e122 VJ |
361 | if (r != 0) { |
362 | printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 363 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
364 | goto end; |
365 | } | |
6530c3d0 | 366 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
367 | |
368 | /* do detect */ | |
369 | SigMatchSignatures(&tv, de_ctx, det_ctx, p3); | |
370 | ||
371 | if (PacketAlertCheck(p3, 1)) { | |
372 | printf("(p3) sig 1 alerted, but it should not have: "); | |
373 | goto end; | |
374 | } | |
375 | if (!(PacketAlertCheck(p3, 2))) { | |
376 | printf("(p3) sig 2 didn't alert, but it should have: "); | |
377 | goto end; | |
378 | } | |
379 | ||
380 | result = 1; | |
381 | ||
382 | end: | |
429c6388 | 383 | if (alp_tctx != NULL) |
fdefb65b | 384 | AppLayerParserThreadCtxFree(alp_tctx); |
e567e122 VJ |
385 | if (det_ctx != NULL) |
386 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
387 | if (de_ctx != NULL) | |
388 | SigGroupCleanup(de_ctx); | |
389 | if (de_ctx != NULL) | |
390 | DetectEngineCtxFree(de_ctx); | |
391 | ||
392 | FLOW_DESTROY(&f); | |
393 | UTHFreePacket(p1); | |
394 | UTHFreePacket(p2); | |
395 | UTHFreePacket(p3); | |
396 | return result; | |
397 | } | |
398 | ||
399 | /** \test simple google.com query matching (TCP) */ | |
8f1d7503 KS |
400 | static int DetectDnsQueryTest03(void) |
401 | { | |
e567e122 VJ |
402 | /* google.com */ |
403 | uint8_t buf[] = { 0x00, 28, | |
404 | 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
405 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
406 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
407 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
408 | 0x00, 0x10, 0x00, 0x01, }; | |
409 | int result = 0; | |
410 | Flow f; | |
411 | DNSState *dns_state = NULL; | |
412 | Packet *p = NULL; | |
413 | Signature *s = NULL; | |
414 | ThreadVars tv; | |
415 | DetectEngineThreadCtx *det_ctx = NULL; | |
416 | TcpSession ssn; | |
8dbf7a0d | 417 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
e567e122 VJ |
418 | |
419 | memset(&tv, 0, sizeof(ThreadVars)); | |
420 | memset(&f, 0, sizeof(Flow)); | |
421 | memset(&ssn, 0, sizeof(TcpSession)); | |
422 | ||
6f8cfd99 AS |
423 | p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_TCP, |
424 | "192.168.1.5", "192.168.1.1", | |
425 | 41424, 53); | |
e567e122 VJ |
426 | |
427 | FLOW_INITIALIZE(&f); | |
428 | f.protoctx = (void *)&ssn; | |
429 | f.flags |= FLOW_IPV4; | |
430 | f.proto = IPPROTO_TCP; | |
a77b9b36 | 431 | f.protomap = FlowGetProtoMapping(f.proto); |
e567e122 VJ |
432 | |
433 | p->flow = &f; | |
434 | p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
435 | p->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED; | |
429c6388 | 436 | f.alproto = ALPROTO_DNS; |
e567e122 VJ |
437 | |
438 | StreamTcpInitConfig(TRUE); | |
439 | ||
440 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
441 | if (de_ctx == NULL) { | |
442 | goto end; | |
443 | } | |
e6044aaf | 444 | de_ctx->mpm_matcher = mpm_default_matcher; |
e567e122 VJ |
445 | de_ctx->flags |= DE_QUIET; |
446 | ||
429c6388 AS |
447 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
448 | "(msg:\"Test dns_query option\"; " | |
449 | "content:\"google\"; nocase; dns_query; sid:1;)"); | |
e567e122 VJ |
450 | if (s == NULL) { |
451 | goto end; | |
452 | } | |
453 | ||
454 | SigGroupBuild(de_ctx); | |
455 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
456 | ||
6530c3d0 | 457 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
458 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
459 | STREAM_TOSERVER, buf, sizeof(buf)); | |
e567e122 VJ |
460 | if (r != 0) { |
461 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 462 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
463 | goto end; |
464 | } | |
6530c3d0 | 465 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
466 | |
467 | dns_state = f.alstate; | |
468 | if (dns_state == NULL) { | |
469 | printf("no dns state: "); | |
470 | goto end; | |
471 | } | |
472 | ||
473 | /* do detect */ | |
474 | SigMatchSignatures(&tv, de_ctx, det_ctx, p); | |
475 | ||
476 | if (!(PacketAlertCheck(p, 1))) { | |
477 | printf("sig 1 didn't alert, but it should have: "); | |
478 | goto end; | |
479 | } | |
480 | ||
481 | result = 1; | |
482 | ||
483 | end: | |
429c6388 | 484 | if (alp_tctx != NULL) |
fdefb65b | 485 | AppLayerParserThreadCtxFree(alp_tctx); |
e567e122 VJ |
486 | if (det_ctx != NULL) |
487 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
488 | if (de_ctx != NULL) | |
489 | SigGroupCleanup(de_ctx); | |
490 | if (de_ctx != NULL) | |
491 | DetectEngineCtxFree(de_ctx); | |
492 | ||
493 | StreamTcpFreeConfig(TRUE); | |
494 | FLOW_DESTROY(&f); | |
495 | UTHFreePacket(p); | |
496 | return result; | |
497 | } | |
498 | ||
499 | /** \test simple google.com query matching (TCP splicing) */ | |
8f1d7503 KS |
500 | static int DetectDnsQueryTest04(void) |
501 | { | |
e567e122 VJ |
502 | /* google.com */ |
503 | uint8_t buf1[] = { 0x00, 28, | |
504 | 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
505 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; | |
506 | uint8_t buf2[] = { 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
507 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
508 | 0x00, 0x10, 0x00, 0x01, }; | |
509 | int result = 0; | |
510 | Flow f; | |
511 | DNSState *dns_state = NULL; | |
512 | Packet *p1 = NULL, *p2 = NULL; | |
513 | Signature *s = NULL; | |
514 | ThreadVars tv; | |
515 | DetectEngineThreadCtx *det_ctx = NULL; | |
516 | TcpSession ssn; | |
8dbf7a0d | 517 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
e567e122 VJ |
518 | |
519 | memset(&tv, 0, sizeof(ThreadVars)); | |
520 | memset(&f, 0, sizeof(Flow)); | |
521 | memset(&ssn, 0, sizeof(TcpSession)); | |
522 | ||
6f8cfd99 AS |
523 | p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_TCP, |
524 | "192.168.1.5", "192.168.1.1", | |
525 | 41424, 53); | |
526 | p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_TCP, | |
527 | "192.168.1.5", "192.168.1.1", | |
528 | 41424, 53); | |
e567e122 VJ |
529 | |
530 | FLOW_INITIALIZE(&f); | |
531 | f.protoctx = (void *)&ssn; | |
532 | f.flags |= FLOW_IPV4; | |
533 | f.proto = IPPROTO_TCP; | |
a77b9b36 | 534 | f.protomap = FlowGetProtoMapping(f.proto); |
429c6388 | 535 | f.alproto = ALPROTO_DNS; |
e567e122 VJ |
536 | |
537 | p1->flow = &f; | |
538 | p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
539 | p1->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED; | |
540 | ||
541 | p2->flow = &f; | |
542 | p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
543 | p2->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED; | |
544 | ||
545 | StreamTcpInitConfig(TRUE); | |
546 | ||
547 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
548 | if (de_ctx == NULL) { | |
549 | goto end; | |
550 | } | |
e6044aaf | 551 | de_ctx->mpm_matcher = mpm_default_matcher; |
e567e122 VJ |
552 | de_ctx->flags |= DE_QUIET; |
553 | ||
429c6388 AS |
554 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
555 | "(msg:\"Test dns_query option\"; " | |
556 | "dns_query; content:\"google\"; nocase; sid:1;)"); | |
e567e122 VJ |
557 | if (s == NULL) { |
558 | goto end; | |
559 | } | |
560 | ||
561 | SigGroupBuild(de_ctx); | |
562 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
563 | ||
6530c3d0 | 564 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
565 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
566 | STREAM_TOSERVER, buf1, sizeof(buf1)); | |
e567e122 VJ |
567 | if (r != 0) { |
568 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 569 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
570 | goto end; |
571 | } | |
6530c3d0 | 572 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
573 | |
574 | dns_state = f.alstate; | |
575 | if (dns_state == NULL) { | |
576 | printf("no dns state: "); | |
577 | goto end; | |
578 | } | |
579 | ||
580 | /* do detect */ | |
581 | SigMatchSignatures(&tv, de_ctx, det_ctx, p1); | |
582 | ||
583 | if (PacketAlertCheck(p1, 1)) { | |
584 | printf("sig 1 alerted, but it should not have: "); | |
585 | goto end; | |
586 | } | |
587 | ||
6530c3d0 | 588 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
589 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER, |
590 | buf2, sizeof(buf2)); | |
e567e122 VJ |
591 | if (r != 0) { |
592 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 593 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
594 | goto end; |
595 | } | |
6530c3d0 | 596 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
597 | |
598 | /* do detect */ | |
599 | SigMatchSignatures(&tv, de_ctx, det_ctx, p2); | |
600 | ||
601 | if (!(PacketAlertCheck(p2, 1))) { | |
602 | printf("sig 1 didn't alert, but it should have: "); | |
603 | goto end; | |
604 | } | |
605 | ||
606 | result = 1; | |
607 | ||
608 | end: | |
429c6388 | 609 | if (alp_tctx != NULL) |
fdefb65b | 610 | AppLayerParserThreadCtxFree(alp_tctx); |
e567e122 VJ |
611 | if (det_ctx != NULL) |
612 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
613 | if (de_ctx != NULL) | |
614 | SigGroupCleanup(de_ctx); | |
615 | if (de_ctx != NULL) | |
616 | DetectEngineCtxFree(de_ctx); | |
617 | ||
618 | StreamTcpFreeConfig(TRUE); | |
619 | FLOW_DESTROY(&f); | |
620 | UTHFreePacket(p1); | |
621 | UTHFreePacket(p2); | |
622 | return result; | |
623 | } | |
624 | ||
625 | /** \test simple google.com query matching (TCP splicing) */ | |
8f1d7503 KS |
626 | static int DetectDnsQueryTest05(void) |
627 | { | |
e567e122 VJ |
628 | /* google.com in 2 chunks (buf1 and buf2) */ |
629 | uint8_t buf1[] = { 0x00, 28, /* len 28 */ | |
630 | 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
631 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; | |
632 | ||
633 | uint8_t buf2[] = { 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
634 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
635 | 0x00, 0x10, 0x00, 0x01, }; | |
636 | ||
637 | uint8_t buf3[] = { 0x00, 44, /* len 44 */ | |
638 | 0x10, 0x32, /* tx id */ | |
639 | 0x81, 0x80, /* flags: resp, recursion desired, recusion available */ | |
640 | 0x00, 0x01, /* 1 query */ | |
641 | 0x00, 0x01, /* 1 answer */ | |
642 | 0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */ | |
643 | /* query record */ | |
644 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */ | |
645 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */ | |
646 | 0x00, 0x01, 0x00, 0x01, /* type a, class in */ | |
647 | /* answer */ | |
648 | 0xc0, 0x0c, /* ref to name in query above */ | |
649 | 0x00, 0x01, 0x00, 0x01, /* type a, class in */ | |
650 | 0x00, 0x01, 0x40, 0xef, /* ttl */ | |
651 | 0x00, 0x04, /* data len */ | |
652 | 0x01, 0x02, 0x03, 0x04 }; /* addr */ | |
653 | ||
654 | /* google.net */ | |
655 | uint8_t buf4[] = { 0x00, 28, /* len 28 */ | |
656 | 0x11, 0x33, 0x01, 0x00, 0x00, 0x01, | |
657 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
658 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
659 | 0x65, 0x03, 0x6E, 0x65, 0x74, 0x00, | |
660 | 0x00, 0x10, 0x00, 0x01, }; | |
661 | int result = 0; | |
662 | Flow f; | |
663 | DNSState *dns_state = NULL; | |
664 | Packet *p1 = NULL, *p2 = NULL, *p3 = NULL, *p4 = NULL; | |
665 | Signature *s = NULL; | |
666 | ThreadVars tv; | |
667 | DetectEngineThreadCtx *det_ctx = NULL; | |
668 | TcpSession ssn; | |
8dbf7a0d | 669 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
e567e122 VJ |
670 | |
671 | memset(&tv, 0, sizeof(ThreadVars)); | |
672 | memset(&f, 0, sizeof(Flow)); | |
673 | memset(&ssn, 0, sizeof(TcpSession)); | |
674 | ||
6f8cfd99 AS |
675 | p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_TCP, |
676 | "192.168.1.5", "192.168.1.1", | |
677 | 41424, 53); | |
678 | p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_TCP, | |
679 | "192.168.1.5", "192.168.1.1", | |
680 | 41424, 53); | |
681 | p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_TCP, | |
682 | "192.168.1.5", "192.168.1.1", | |
683 | 41424, 53); | |
684 | p4 = UTHBuildPacketReal(buf4, sizeof(buf4), IPPROTO_TCP, | |
685 | "192.168.1.5", "192.168.1.1", | |
686 | 41424, 53); | |
e567e122 VJ |
687 | |
688 | FLOW_INITIALIZE(&f); | |
689 | f.protoctx = (void *)&ssn; | |
690 | f.flags |= FLOW_IPV4; | |
691 | f.proto = IPPROTO_TCP; | |
a77b9b36 | 692 | f.protomap = FlowGetProtoMapping(f.proto); |
429c6388 | 693 | f.alproto = ALPROTO_DNS; |
e567e122 VJ |
694 | |
695 | p1->flow = &f; | |
696 | p1->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
697 | p1->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED; | |
698 | ||
699 | p2->flow = &f; | |
700 | p2->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
701 | p2->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED; | |
702 | ||
703 | p3->flow = &f; | |
704 | p3->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
705 | p3->flowflags |= FLOW_PKT_TOCLIENT|FLOW_PKT_ESTABLISHED; | |
706 | ||
707 | p4->flow = &f; | |
708 | p4->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; | |
709 | p4->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED; | |
710 | ||
711 | StreamTcpInitConfig(TRUE); | |
712 | ||
713 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
714 | if (de_ctx == NULL) { | |
715 | goto end; | |
716 | } | |
e6044aaf | 717 | de_ctx->mpm_matcher = mpm_default_matcher; |
e567e122 VJ |
718 | de_ctx->flags |= DE_QUIET; |
719 | ||
429c6388 AS |
720 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
721 | "(msg:\"Test dns_query option\"; " | |
722 | "dns_query; content:\"google.com\"; nocase; sid:1;)"); | |
e567e122 VJ |
723 | if (s == NULL) { |
724 | goto end; | |
725 | } | |
429c6388 AS |
726 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
727 | "(msg:\"Test dns_query option\"; " | |
728 | "dns_query; content:\"google.net\"; nocase; sid:2;)"); | |
e567e122 VJ |
729 | if (s == NULL) { |
730 | goto end; | |
731 | } | |
732 | ||
733 | SigGroupBuild(de_ctx); | |
734 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
735 | ||
6530c3d0 | 736 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
737 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
738 | STREAM_TOSERVER, buf1, sizeof(buf1)); | |
e567e122 VJ |
739 | if (r != 0) { |
740 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 741 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
742 | goto end; |
743 | } | |
6530c3d0 | 744 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
745 | |
746 | dns_state = f.alstate; | |
747 | if (dns_state == NULL) { | |
748 | printf("no dns state: "); | |
749 | goto end; | |
750 | } | |
751 | ||
752 | /* do detect */ | |
753 | SigMatchSignatures(&tv, de_ctx, det_ctx, p1); | |
754 | ||
755 | if (PacketAlertCheck(p1, 1)) { | |
756 | printf("(p1) sig 1 alerted, but it should not have: "); | |
757 | goto end; | |
758 | } | |
759 | if (PacketAlertCheck(p1, 2)) { | |
760 | printf("(p1) sig 2 did alert, but it should not have: "); | |
761 | goto end; | |
762 | } | |
763 | ||
6530c3d0 | 764 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
765 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER, |
766 | buf2, sizeof(buf2)); | |
e567e122 VJ |
767 | if (r != 0) { |
768 | printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 769 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
770 | goto end; |
771 | } | |
6530c3d0 | 772 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
773 | |
774 | /* do detect */ | |
775 | SigMatchSignatures(&tv, de_ctx, det_ctx, p2); | |
776 | ||
777 | if (!(PacketAlertCheck(p2, 1))) { | |
778 | printf("sig 1 didn't alert, but it should have: "); | |
779 | goto end; | |
780 | } | |
781 | if (PacketAlertCheck(p2, 2)) { | |
782 | printf("(p2) sig 2 did alert, but it should not have: "); | |
783 | goto end; | |
784 | } | |
785 | ||
6530c3d0 | 786 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
787 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT, |
788 | buf3, sizeof(buf3)); | |
e567e122 VJ |
789 | if (r != 0) { |
790 | printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 791 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
792 | goto end; |
793 | } | |
6530c3d0 | 794 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
795 | |
796 | /* do detect */ | |
797 | SigMatchSignatures(&tv, de_ctx, det_ctx, p3); | |
798 | ||
799 | if (PacketAlertCheck(p3, 1)) { | |
800 | printf("sig 1 did alert, but it should not have: "); | |
801 | goto end; | |
802 | } | |
803 | if (PacketAlertCheck(p3, 2)) { | |
804 | printf("(p3) sig 2 did alert, but it should not have: "); | |
805 | goto end; | |
806 | } | |
807 | ||
6530c3d0 | 808 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
809 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER, |
810 | buf4, sizeof(buf4)); | |
e567e122 VJ |
811 | if (r != 0) { |
812 | printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 813 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
814 | goto end; |
815 | } | |
6530c3d0 | 816 | FLOWLOCK_UNLOCK(&f); |
e567e122 VJ |
817 | |
818 | /* do detect */ | |
819 | SigMatchSignatures(&tv, de_ctx, det_ctx, p4); | |
820 | ||
821 | if (PacketAlertCheck(p4, 1)) { | |
822 | printf("(p4) sig 1 did alert, but it should not have: "); | |
823 | goto end; | |
824 | } | |
825 | if (!(PacketAlertCheck(p4, 2))) { | |
826 | printf("sig 1 didn't alert, but it should have: "); | |
827 | goto end; | |
828 | } | |
829 | ||
830 | result = 1; | |
831 | ||
832 | end: | |
429c6388 | 833 | if (alp_tctx != NULL) |
fdefb65b | 834 | AppLayerParserThreadCtxFree(alp_tctx); |
e567e122 VJ |
835 | if (det_ctx != NULL) |
836 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
837 | if (de_ctx != NULL) | |
838 | SigGroupCleanup(de_ctx); | |
839 | if (de_ctx != NULL) | |
840 | DetectEngineCtxFree(de_ctx); | |
841 | ||
842 | StreamTcpFreeConfig(TRUE); | |
843 | FLOW_DESTROY(&f); | |
844 | UTHFreePacket(p1); | |
845 | UTHFreePacket(p2); | |
846 | UTHFreePacket(p3); | |
847 | UTHFreePacket(p4); | |
848 | return result; | |
849 | } | |
4817e130 VJ |
850 | |
851 | /** \test simple google.com query matching, pcre */ | |
8f1d7503 KS |
852 | static int DetectDnsQueryTest06(void) |
853 | { | |
4817e130 VJ |
854 | /* google.com */ |
855 | uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
856 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
857 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
858 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
859 | 0x00, 0x10, 0x00, 0x01, }; | |
860 | int result = 0; | |
861 | Flow f; | |
862 | DNSState *dns_state = NULL; | |
863 | Packet *p = NULL; | |
864 | Signature *s = NULL; | |
865 | ThreadVars tv; | |
866 | DetectEngineThreadCtx *det_ctx = NULL; | |
8dbf7a0d | 867 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
4817e130 VJ |
868 | |
869 | memset(&tv, 0, sizeof(ThreadVars)); | |
870 | memset(&f, 0, sizeof(Flow)); | |
871 | ||
6f8cfd99 AS |
872 | p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP, |
873 | "192.168.1.5", "192.168.1.1", | |
874 | 41424, 53); | |
4817e130 VJ |
875 | |
876 | FLOW_INITIALIZE(&f); | |
877 | f.flags |= FLOW_IPV4; | |
878 | f.proto = IPPROTO_UDP; | |
a77b9b36 | 879 | f.protomap = FlowGetProtoMapping(f.proto); |
4817e130 VJ |
880 | |
881 | p->flow = &f; | |
882 | p->flags |= PKT_HAS_FLOW; | |
883 | p->flowflags |= FLOW_PKT_TOSERVER; | |
429c6388 | 884 | f.alproto = ALPROTO_DNS; |
4817e130 VJ |
885 | |
886 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
887 | if (de_ctx == NULL) { | |
888 | goto end; | |
889 | } | |
e6044aaf | 890 | de_ctx->mpm_matcher = mpm_default_matcher; |
4817e130 VJ |
891 | de_ctx->flags |= DE_QUIET; |
892 | ||
f592c481 | 893 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
429c6388 AS |
894 | "(msg:\"Test dns_query option\"; " |
895 | "dns_query; content:\"google\"; nocase; " | |
896 | "pcre:\"/google\\.com$/i\"; sid:1;)"); | |
4817e130 VJ |
897 | if (s == NULL) { |
898 | goto end; | |
899 | } | |
f592c481 | 900 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
4817e130 | 901 | "(msg:\"Test dns_query option\"; " |
f353fb63 VJ |
902 | "dns_query; content:\"google\"; nocase; " |
903 | "pcre:\"/^\\.[a-z]{2,3}$/iR\"; sid:2;)"); | |
4817e130 VJ |
904 | if (s == NULL) { |
905 | goto end; | |
906 | } | |
907 | ||
908 | ||
909 | SigGroupBuild(de_ctx); | |
910 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
911 | ||
6530c3d0 | 912 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
913 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
914 | STREAM_TOSERVER, buf, sizeof(buf)); | |
4817e130 VJ |
915 | if (r != 0) { |
916 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 917 | FLOWLOCK_UNLOCK(&f); |
4817e130 VJ |
918 | goto end; |
919 | } | |
6530c3d0 | 920 | FLOWLOCK_UNLOCK(&f); |
4817e130 VJ |
921 | |
922 | dns_state = f.alstate; | |
923 | if (dns_state == NULL) { | |
924 | printf("no dns state: "); | |
925 | goto end; | |
926 | } | |
927 | ||
928 | /* do detect */ | |
929 | SigMatchSignatures(&tv, de_ctx, det_ctx, p); | |
930 | ||
931 | if (!(PacketAlertCheck(p, 1))) { | |
932 | printf("sig 1 didn't alert, but it should have: "); | |
933 | goto end; | |
934 | } | |
935 | if (!(PacketAlertCheck(p, 2))) { | |
936 | printf("sig 2 didn't alert, but it should have: "); | |
937 | goto end; | |
938 | } | |
939 | ||
940 | result = 1; | |
941 | ||
942 | end: | |
429c6388 | 943 | if (alp_tctx != NULL) |
fdefb65b | 944 | AppLayerParserThreadCtxFree(alp_tctx); |
4817e130 VJ |
945 | if (det_ctx != NULL) |
946 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
947 | if (de_ctx != NULL) | |
948 | SigGroupCleanup(de_ctx); | |
949 | if (de_ctx != NULL) | |
950 | DetectEngineCtxFree(de_ctx); | |
951 | ||
952 | FLOW_DESTROY(&f); | |
953 | UTHFreePacket(p); | |
954 | return result; | |
955 | } | |
956 | ||
28a6c1d9 VJ |
957 | /** \test multi tx google.(com|net) query matching + |
958 | * app layer event */ | |
8f1d7503 KS |
959 | static int DetectDnsQueryTest07(void) |
960 | { | |
28a6c1d9 VJ |
961 | /* google.com */ |
962 | uint8_t buf1[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01, | |
963 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
964 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
965 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, | |
966 | 0x00, 0x01, 0x00, 0x01, }; | |
967 | ||
968 | uint8_t buf2[] = { 0x10, 0x32, /* tx id */ | |
969 | 0x81, 0x80|0x40, /* flags: resp, recursion desired, recusion available */ | |
970 | 0x00, 0x01, /* 1 query */ | |
971 | 0x00, 0x01, /* 1 answer */ | |
972 | 0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */ | |
973 | /* query record */ | |
974 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */ | |
975 | 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */ | |
976 | 0x00, 0x01, 0x00, 0x01, /* type a, class in */ | |
977 | /* answer */ | |
978 | 0xc0, 0x0c, /* ref to name in query above */ | |
979 | 0x00, 0x01, 0x00, 0x01, /* type a, class in */ | |
980 | 0x00, 0x01, 0x40, 0xef, /* ttl */ | |
981 | 0x00, 0x04, /* data len */ | |
982 | 0x01, 0x02, 0x03, 0x04 }; /* addr */ | |
983 | ||
984 | /* google.net */ | |
985 | uint8_t buf3[] = { 0x11, 0x33, 0x01, 0x00, 0x00, 0x01, | |
986 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
987 | 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, | |
988 | 0x65, 0x03, 0x6E, 0x65, 0x74, 0x00, | |
989 | 0x00, 0x10, 0x00, 0x01, }; | |
990 | int result = 0; | |
991 | Flow f; | |
992 | DNSState *dns_state = NULL; | |
993 | Packet *p1 = NULL, *p2 = NULL, *p3 = NULL; | |
994 | Signature *s = NULL; | |
995 | ThreadVars tv; | |
996 | DetectEngineThreadCtx *det_ctx = NULL; | |
8dbf7a0d | 997 | AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); |
28a6c1d9 VJ |
998 | |
999 | memset(&tv, 0, sizeof(ThreadVars)); | |
1000 | memset(&f, 0, sizeof(Flow)); | |
1001 | ||
6f8cfd99 AS |
1002 | p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP, |
1003 | "192.168.1.5", "192.168.1.1", | |
1004 | 41424, 53); | |
1005 | p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_UDP, | |
1006 | "192.168.1.5", "192.168.1.1", | |
1007 | 41424, 53); | |
1008 | p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_UDP, | |
1009 | "192.168.1.5", "192.168.1.1", | |
1010 | 41424, 53); | |
28a6c1d9 VJ |
1011 | |
1012 | FLOW_INITIALIZE(&f); | |
1013 | f.flags |= FLOW_IPV4; | |
1014 | f.proto = IPPROTO_UDP; | |
a77b9b36 | 1015 | f.protomap = FlowGetProtoMapping(f.proto); |
429c6388 | 1016 | f.alproto = ALPROTO_DNS; |
28a6c1d9 VJ |
1017 | |
1018 | p1->flow = &f; | |
1019 | p1->flags |= PKT_HAS_FLOW; | |
1020 | p1->flowflags |= FLOW_PKT_TOSERVER; | |
1021 | p1->pcap_cnt = 1; | |
1022 | ||
1023 | p2->flow = &f; | |
1024 | p2->flags |= PKT_HAS_FLOW; | |
1025 | p2->flowflags |= FLOW_PKT_TOCLIENT; | |
1026 | p2->pcap_cnt = 2; | |
1027 | ||
1028 | p3->flow = &f; | |
1029 | p3->flags |= PKT_HAS_FLOW; | |
1030 | p3->flowflags |= FLOW_PKT_TOSERVER; | |
1031 | p3->pcap_cnt = 3; | |
1032 | ||
1033 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
1034 | if (de_ctx == NULL) { | |
1035 | goto end; | |
1036 | } | |
e6044aaf | 1037 | de_ctx->mpm_matcher = mpm_default_matcher; |
28a6c1d9 VJ |
1038 | de_ctx->flags |= DE_QUIET; |
1039 | ||
f592c481 | 1040 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
28a6c1d9 | 1041 | "(msg:\"Test dns_query option\"; " |
f353fb63 | 1042 | "dns_query; content:\"google.com\"; nocase; sid:1;)"); |
28a6c1d9 VJ |
1043 | if (s == NULL) { |
1044 | goto end; | |
1045 | } | |
f592c481 | 1046 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
28a6c1d9 | 1047 | "(msg:\"Test dns_query option\"; " |
f353fb63 | 1048 | "dns_query; content:\"google.net\"; nocase; sid:2;)"); |
28a6c1d9 VJ |
1049 | if (s == NULL) { |
1050 | goto end; | |
1051 | } | |
f592c481 | 1052 | s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any " |
28a6c1d9 VJ |
1053 | "(msg:\"Test Z flag event\"; " |
1054 | "app-layer-event:dns.z_flag_set; sid:3;)"); | |
1055 | if (s == NULL) { | |
1056 | goto end; | |
1057 | } | |
1058 | ||
1059 | SigGroupBuild(de_ctx); | |
1060 | DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); | |
1061 | ||
6530c3d0 | 1062 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
1063 | int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, |
1064 | STREAM_TOSERVER, buf1, sizeof(buf1)); | |
28a6c1d9 VJ |
1065 | if (r != 0) { |
1066 | printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 1067 | FLOWLOCK_UNLOCK(&f); |
28a6c1d9 VJ |
1068 | goto end; |
1069 | } | |
6530c3d0 | 1070 | FLOWLOCK_UNLOCK(&f); |
28a6c1d9 VJ |
1071 | |
1072 | dns_state = f.alstate; | |
1073 | if (dns_state == NULL) { | |
1074 | printf("no dns state: "); | |
1075 | goto end; | |
1076 | } | |
1077 | ||
1078 | /* do detect */ | |
1079 | SigMatchSignatures(&tv, de_ctx, det_ctx, p1); | |
1080 | ||
1081 | if (!(PacketAlertCheck(p1, 1))) { | |
1082 | printf("(p1) sig 1 didn't alert, but it should have: "); | |
1083 | goto end; | |
1084 | } | |
1085 | if (PacketAlertCheck(p1, 2)) { | |
1086 | printf("(p1) sig 2 did alert, but it should not have: "); | |
1087 | goto end; | |
1088 | } | |
1089 | ||
6530c3d0 | 1090 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
1091 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT, |
1092 | buf2, sizeof(buf2)); | |
28a6c1d9 VJ |
1093 | if (r != -1) { |
1094 | printf("toserver client 1 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 1095 | FLOWLOCK_UNLOCK(&f); |
28a6c1d9 VJ |
1096 | goto end; |
1097 | } | |
6530c3d0 | 1098 | FLOWLOCK_UNLOCK(&f); |
28a6c1d9 VJ |
1099 | |
1100 | /* do detect */ | |
1101 | SigMatchSignatures(&tv, de_ctx, det_ctx, p2); | |
1102 | ||
1103 | if (PacketAlertCheck(p2, 1)) { | |
1104 | printf("(p2) sig 1 alerted, but it should not have: "); | |
1105 | goto end; | |
1106 | } | |
1107 | if (PacketAlertCheck(p2, 2)) { | |
1108 | printf("(p2) sig 2 alerted, but it should not have: "); | |
1109 | goto end; | |
1110 | } | |
1111 | if (!(PacketAlertCheck(p2, 3))) { | |
1112 | printf("(p2) sig 3 didn't alert, but it should have: "); | |
1113 | goto end; | |
1114 | } | |
1115 | ||
6530c3d0 | 1116 | FLOWLOCK_WRLOCK(&f); |
675fa564 GL |
1117 | r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER, |
1118 | buf3, sizeof(buf3)); | |
28a6c1d9 VJ |
1119 | if (r != 0) { |
1120 | printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r); | |
6530c3d0 | 1121 | FLOWLOCK_UNLOCK(&f); |
28a6c1d9 VJ |
1122 | goto end; |
1123 | } | |
6530c3d0 | 1124 | FLOWLOCK_UNLOCK(&f); |
28a6c1d9 VJ |
1125 | |
1126 | /* do detect */ | |
1127 | SigMatchSignatures(&tv, de_ctx, det_ctx, p3); | |
1128 | ||
1129 | if (PacketAlertCheck(p3, 1)) { | |
1130 | printf("(p3) sig 1 alerted, but it should not have: "); | |
1131 | goto end; | |
1132 | } | |
1133 | if (!(PacketAlertCheck(p3, 2))) { | |
1134 | printf("(p3) sig 2 didn't alert, but it should have: "); | |
1135 | goto end; | |
1136 | } | |
72e35efb | 1137 | /** \todo should not alert, bug #839 |
28a6c1d9 | 1138 | if (PacketAlertCheck(p3, 3)) { |
72e35efb | 1139 | printf("(p3) sig 3 did alert, but it should not have: "); |
28a6c1d9 VJ |
1140 | goto end; |
1141 | } | |
72e35efb | 1142 | */ |
28a6c1d9 VJ |
1143 | result = 1; |
1144 | ||
1145 | end: | |
429c6388 | 1146 | if (alp_tctx != NULL) |
fdefb65b | 1147 | AppLayerParserThreadCtxFree(alp_tctx); |
28a6c1d9 VJ |
1148 | if (det_ctx != NULL) |
1149 | DetectEngineThreadCtxDeinit(&tv, det_ctx); | |
1150 | if (de_ctx != NULL) | |
1151 | SigGroupCleanup(de_ctx); | |
1152 | if (de_ctx != NULL) | |
1153 | DetectEngineCtxFree(de_ctx); | |
1154 | ||
1155 | FLOW_DESTROY(&f); | |
1156 | UTHFreePacket(p1); | |
1157 | UTHFreePacket(p2); | |
1158 | UTHFreePacket(p3); | |
1159 | return result; | |
1160 | } | |
1161 | ||
e567e122 VJ |
1162 | #endif |
1163 | ||
8f1d7503 KS |
1164 | static void DetectDnsQueryRegisterTests(void) |
1165 | { | |
e567e122 | 1166 | #ifdef UNITTESTS |
796dd522 JI |
1167 | UtRegisterTest("DetectDnsQueryTest01", DetectDnsQueryTest01); |
1168 | UtRegisterTest("DetectDnsQueryTest02", DetectDnsQueryTest02); | |
1169 | UtRegisterTest("DetectDnsQueryTest03 -- tcp", DetectDnsQueryTest03); | |
1170 | UtRegisterTest("DetectDnsQueryTest04 -- tcp splicing", | |
1171 | DetectDnsQueryTest04); | |
1172 | UtRegisterTest("DetectDnsQueryTest05 -- tcp splicing/multi tx", | |
1173 | DetectDnsQueryTest05); | |
1174 | UtRegisterTest("DetectDnsQueryTest06 -- pcre", DetectDnsQueryTest06); | |
1175 | UtRegisterTest("DetectDnsQueryTest07 -- app layer event", | |
1176 | DetectDnsQueryTest07); | |
e567e122 VJ |
1177 | #endif |
1178 | } |