suricata
detect-dns-query.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2018 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"
42 #include "detect-content.h"
43 #include "detect-pcre.h"
44 
45 #include "flow.h"
46 #include "flow-util.h"
47 #include "flow-var.h"
48 
49 #include "util-debug.h"
50 #include "util-unittest.h"
51 #include "util-spm.h"
52 #include "util-print.h"
53 
54 #include "stream-tcp.h"
55 
56 #include "app-layer.h"
57 #include "app-layer-dns-common.h"
58 #include "detect-dns-query.h"
59 #include "detect-engine-dns.h"
60 
61 #include "util-unittest-helper.h"
62 
63 #ifdef HAVE_RUST
64 #include "rust-dns-dns-gen.h"
65 #endif
66 
67 static int DetectDnsQuerySetup (DetectEngineCtx *, Signature *, const char *);
68 static void DetectDnsQueryRegisterTests(void);
69 static int g_dns_query_buffer_id = 0;
70 
72  int local_id; /**< used as index into thread inspect array */
73 #ifdef HAVE_RUST
74  void *txv;
75 #else
77 #endif
78 };
79 
80 static InspectionBuffer *DnsQueryGetData(DetectEngineThreadCtx *det_ctx,
81  const DetectEngineTransforms *transforms,
82  Flow *f, struct DnsQueryGetDataArgs *cbdata, int list_id, bool first)
83 {
84  SCEnter();
85 
88  if (buffer == NULL)
89  return NULL;
90  if (!first && buffer->inspect != NULL)
91  return buffer;
92 
93  const uint8_t *data;
94  uint32_t data_len;
95 #ifdef HAVE_RUST
96  if (rs_dns_tx_get_query_name(cbdata->txv, (uint16_t)cbdata->local_id,
97  (uint8_t **)&data, &data_len) == 0) {
98  return NULL;
99  }
100 #else
101  const DNSQueryEntry *query = cbdata->query;
102  data = (const uint8_t *)((uint8_t *)query + sizeof(DNSQueryEntry));
103  data_len = query->len;
104 #endif
105  InspectionBufferSetup(buffer, data, data_len);
106  InspectionBufferApplyTransforms(buffer, transforms);
107 
108  SCReturnPtr(buffer, "InspectionBuffer");
109 }
110 
111 static int DetectEngineInspectDnsQuery(
112  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
113  const DetectEngineAppInspectionEngine *engine,
114  const Signature *s,
115  Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
116 {
117  int local_id = 0;
118 
119  const DetectEngineTransforms *transforms = NULL;
120  if (!engine->mpm) {
121  transforms = engine->v2.transforms;
122  }
123 
124 #ifdef HAVE_RUST
125  while(1) {
126  struct DnsQueryGetDataArgs cbdata = { local_id, txv, };
127  InspectionBuffer *buffer = DnsQueryGetData(det_ctx,
128  transforms, f, &cbdata, engine->sm_list, false);
129  if (buffer == NULL || buffer->inspect == NULL)
130  break;
131 
132  det_ctx->buffer_offset = 0;
133  det_ctx->discontinue_matching = 0;
134  det_ctx->inspection_recursion_counter = 0;
135 
136  const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,
137  f,
138  (uint8_t *)buffer->inspect,
139  buffer->inspect_len,
142  if (match == 1) {
144  }
145  local_id++;
146  }
147 #else
148  DNSTransaction *tx = (DNSTransaction *)txv;
149  DNSQueryEntry *query = NULL;
150  TAILQ_FOREACH(query, &tx->query_list, next)
151  {
152  struct DnsQueryGetDataArgs cbdata = { local_id, query };
153  InspectionBuffer *buffer = DnsQueryGetData(det_ctx,
154  transforms, f, &cbdata, engine->sm_list, false);
155  if (buffer == NULL || buffer->inspect == NULL)
156  break;
157 
158  det_ctx->buffer_offset = 0;
159  det_ctx->discontinue_matching = 0;
160  det_ctx->inspection_recursion_counter = 0;
161 
162  const int match = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd,
163  f,
164  (uint8_t *)buffer->inspect,
165  buffer->inspect_len,
168  if (match == 1) {
170  }
171  local_id++;
172  }
173 #endif
175 }
176 
177 typedef struct PrefilterMpmDnsQuery {
178  int list_id;
179  const MpmCtx *mpm_ctx;
182 
183 /** \brief DnsQuery DnsQuery Mpm prefilter callback
184  *
185  * \param det_ctx detection engine thread ctx
186  * \param p packet to inspect
187  * \param f flow to inspect
188  * \param txv tx to inspect
189  * \param pectx inspection context
190  */
191 static void PrefilterTxDnsQuery(DetectEngineThreadCtx *det_ctx,
192  const void *pectx,
193  Packet *p, Flow *f, void *txv,
194  const uint64_t idx, const uint8_t flags)
195 {
196  SCEnter();
197 
198  const PrefilterMpmDnsQuery *ctx = (const PrefilterMpmDnsQuery *)pectx;
199  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
200  const int list_id = ctx->list_id;
201 
202  int local_id = 0;
203 #ifdef HAVE_RUST
204  while(1) {
205  // loop until we get a NULL
206 
207  struct DnsQueryGetDataArgs cbdata = { local_id, txv };
208  InspectionBuffer *buffer = DnsQueryGetData(det_ctx, ctx->transforms,
209  f, &cbdata, list_id, true);
210  if (buffer == NULL)
211  break;
212 
213  if (buffer->inspect_len >= mpm_ctx->minlen) {
214  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
215  &det_ctx->mtcu, &det_ctx->pmq,
216  buffer->inspect, buffer->inspect_len);
217  }
218 
219  local_id++;
220  }
221 #else
222  const DNSTransaction *tx = (DNSTransaction *)txv;
223  const DNSQueryEntry *query = NULL;
224  TAILQ_FOREACH(query, &tx->query_list, next)
225  {
226  struct DnsQueryGetDataArgs cbdata = { local_id, query };
227  InspectionBuffer *buffer = DnsQueryGetData(det_ctx, ctx->transforms,
228  f, &cbdata, list_id, true);
229 
230  if (buffer != NULL && buffer->inspect_len >= mpm_ctx->minlen) {
231  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
232  &det_ctx->mtcu, &det_ctx->pmq,
233  buffer->inspect, buffer->inspect_len);
234  }
235  local_id++;
236  }
237 #endif
238 }
239 
240 static void PrefilterMpmDnsQueryFree(void *ptr)
241 {
242  SCFree(ptr);
243 }
244 
245 static int PrefilterMpmDnsQueryRegister(DetectEngineCtx *de_ctx,
246  SigGroupHead *sgh, MpmCtx *mpm_ctx,
247  const DetectMpmAppLayerRegistery *mpm_reg, int list_id)
248 {
249  PrefilterMpmDnsQuery *pectx = SCCalloc(1, sizeof(*pectx));
250  if (pectx == NULL)
251  return -1;
252  pectx->list_id = list_id;
253  pectx->mpm_ctx = mpm_ctx;
254  pectx->transforms = &mpm_reg->v2.transforms;
255 
256  return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxDnsQuery,
257  mpm_reg->v2.alproto, mpm_reg->v2.tx_min_progress,
258  pectx, PrefilterMpmDnsQueryFree, mpm_reg->name);
259 }
260 
261 
262 /**
263  * \brief Registration function for keyword: dns_query
264  */
266 {
267  sigmatch_table[DETECT_AL_DNS_QUERY].name = "dns_query";
268  sigmatch_table[DETECT_AL_DNS_QUERY].desc = "content modifier to match specifically and only on the DNS query-buffer";
270  sigmatch_table[DETECT_AL_DNS_QUERY].Setup = DetectDnsQuerySetup;
272  sigmatch_table[DETECT_AL_DNS_QUERY].RegisterTests = DetectDnsQueryRegisterTests;
273 
275 
277  PrefilterMpmDnsQueryRegister, NULL,
278  ALPROTO_DNS, 1);
279 
282  DetectEngineInspectDnsQuery, NULL);
283 
285  "dns request query");
286 
287  g_dns_query_buffer_id = DetectBufferTypeGetByName("dns_query");
288 
289  /* register these generic engines from here for now */
296 
298  "dns requests");
300  "dns responses");
301 }
302 
303 
304 /**
305  * \brief this function setups the dns_query modifier keyword used in the rule
306  *
307  * \param de_ctx Pointer to the Detection Engine Context
308  * \param s Pointer to the Signature to which the current keyword belongs
309  * \param str Should hold an empty string always
310  *
311  * \retval 0 On success
312  * \retval -1 On failure
313  */
314 
315 static int DetectDnsQuerySetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
316 {
317  DetectBufferSetActiveList(s, g_dns_query_buffer_id);
318  s->alproto = ALPROTO_DNS;
319  return 0;
320 }
321 
322 #ifdef UNITTESTS
323 #include "detect-isdataat.h"
324 
325 /** \test simple google.com query matching */
326 static int DetectDnsQueryTest01(void)
327 {
328  /* google.com */
329  uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
330  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
332  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
333  0x00, 0x10, 0x00, 0x01, };
334  Flow f;
335  DNSState *dns_state = NULL;
336  Packet *p = NULL;
337  Signature *s = NULL;
338  ThreadVars tv;
339  DetectEngineThreadCtx *det_ctx = NULL;
341 
342  memset(&tv, 0, sizeof(ThreadVars));
343  memset(&f, 0, sizeof(Flow));
344 
345  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP,
346  "192.168.1.5", "192.168.1.1",
347  41424, 53);
348 
349  FLOW_INITIALIZE(&f);
350  f.flags |= FLOW_IPV4;
351  f.proto = IPPROTO_UDP;
353 
354  p->flow = &f;
355  p->flags |= PKT_HAS_FLOW;
357  f.alproto = ALPROTO_DNS;
358 
360  FAIL_IF_NULL(de_ctx);
362  de_ctx->flags |= DE_QUIET;
363 
364  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
365  "(msg:\"Test dns_query option\"; "
366  "dns_query; content:\"google\"; nocase; sid:1;)");
367  FAIL_IF_NULL(s);
368 
369  SigGroupBuild(de_ctx);
370  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
371 
372  FLOWLOCK_WRLOCK(&f);
373  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
374  STREAM_TOSERVER, buf, sizeof(buf));
375  if (r != 0) {
376  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
377  FLOWLOCK_UNLOCK(&f);
378  FAIL;
379  }
380  FLOWLOCK_UNLOCK(&f);
381 
382  dns_state = f.alstate;
383  FAIL_IF_NULL(dns_state);
384 
385  /* do detect */
386  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
387 
388  if (!(PacketAlertCheck(p, 1))) {
389  printf("sig 1 didn't alert, but it should have: ");
390  FAIL;
391  }
392 
393  if (alp_tctx != NULL)
394  AppLayerParserThreadCtxFree(alp_tctx);
395  if (det_ctx != NULL)
396  DetectEngineThreadCtxDeinit(&tv, det_ctx);
397  if (de_ctx != NULL)
398  SigGroupCleanup(de_ctx);
399  if (de_ctx != NULL)
400  DetectEngineCtxFree(de_ctx);
401 
402  FLOW_DESTROY(&f);
403  UTHFreePacket(p);
404  PASS;
405 }
406 
407 /** \test multi tx google.(com|net) query matching */
408 static int DetectDnsQueryTest02(void)
409 {
410  /* google.com */
411  uint8_t buf1[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
412  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
414  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
415  0x00, 0x01, 0x00, 0x01, };
416 
417  uint8_t buf2[] = { 0x10, 0x32, /* tx id */
418  0x81, 0x80, /* flags: resp, recursion desired, recusion available */
419  0x00, 0x01, /* 1 query */
420  0x00, 0x01, /* 1 answer */
421  0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */
422  /* query record */
423  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */
424  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */
425  0x00, 0x01, 0x00, 0x01, /* type a, class in */
426  /* answer */
427  0xc0, 0x0c, /* ref to name in query above */
428  0x00, 0x01, 0x00, 0x01, /* type a, class in */
429  0x00, 0x01, 0x40, 0xef, /* ttl */
430  0x00, 0x04, /* data len */
431  0x01, 0x02, 0x03, 0x04 }; /* addr */
432 
433  /* google.net */
434  uint8_t buf3[] = { 0x11, 0x33, 0x01, 0x00, 0x00, 0x01,
435  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
437  0x65, 0x03, 0x6E, 0x65, 0x74, 0x00,
438  0x00, 0x10, 0x00, 0x01, };
439  Flow f;
440  DNSState *dns_state = NULL;
441  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
442  Signature *s = NULL;
443  ThreadVars tv;
444  DetectEngineThreadCtx *det_ctx = NULL;
446 
447  memset(&tv, 0, sizeof(ThreadVars));
448  memset(&f, 0, sizeof(Flow));
449 
450  p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
451  "192.168.1.5", "192.168.1.1",
452  41424, 53);
453  p2 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
454  "192.168.1.5", "192.168.1.1",
455  41424, 53);
456  p3 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
457  "192.168.1.5", "192.168.1.1",
458  41424, 53);
459 
460  FLOW_INITIALIZE(&f);
461  f.flags |= FLOW_IPV4;
462  f.proto = IPPROTO_UDP;
464  f.alproto = ALPROTO_DNS;
465 
466  p1->flow = &f;
467  p1->flags |= PKT_HAS_FLOW;
469  p1->pcap_cnt = 1;
470 
471  p2->flow = &f;
472  p2->flags |= PKT_HAS_FLOW;
473  p2->flowflags |= FLOW_PKT_TOCLIENT;
474  p2->pcap_cnt = 2;
475 
476  p3->flow = &f;
477  p3->flags |= PKT_HAS_FLOW;
478  p3->flowflags |= FLOW_PKT_TOSERVER;
479  p3->pcap_cnt = 3;
480 
482  FAIL_IF_NULL(de_ctx);
484  de_ctx->flags |= DE_QUIET;
485 
486  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
487  "(msg:\"Test dns_query option\"; "
488  "dns_query; content:\"google.com\"; nocase; sid:1;)");
489  FAIL_IF_NULL(s);
490  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
491  "(msg:\"Test dns_query option\"; "
492  "dns_query; content:\"google.net\"; nocase; sid:2;)");
493  FAIL_IF_NULL(s);
494 
495  SigGroupBuild(de_ctx);
496  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
497 
498  FLOWLOCK_WRLOCK(&f);
499  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
500  STREAM_TOSERVER, buf1, sizeof(buf1));
501  if (r != 0) {
502  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
503  FLOWLOCK_UNLOCK(&f);
504  FAIL;
505  }
506  FLOWLOCK_UNLOCK(&f);
507 
508  dns_state = f.alstate;
509  FAIL_IF_NULL(dns_state);
510 
511  /* do detect */
512  SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
513 
514  if (!(PacketAlertCheck(p1, 1))) {
515  printf("(p1) sig 1 didn't alert, but it should have: ");
516  FAIL;
517  }
518  if (PacketAlertCheck(p1, 2)) {
519  printf("(p1) sig 2 did alert, but it should not have: ");
520  FAIL;
521  }
522 
523  FLOWLOCK_WRLOCK(&f);
524  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT,
525  buf2, sizeof(buf2));
526  if (r != 0) {
527  printf("toserver client 1 returned %" PRId32 ", expected 0: ", r);
528  FLOWLOCK_UNLOCK(&f);
529  FAIL;
530  }
531  FLOWLOCK_UNLOCK(&f);
532 
533  /* do detect */
534  SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
535 
536  if (PacketAlertCheck(p2, 1)) {
537  printf("(p2) sig 1 alerted, but it should not have: ");
538  FAIL;
539  }
540  if (PacketAlertCheck(p2, 2)) {
541  printf("(p2) sig 2 alerted, but it should not have: ");
542  FAIL;
543  }
544 
545  FLOWLOCK_WRLOCK(&f);
546  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
547  buf3, sizeof(buf3));
548  if (r != 0) {
549  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
550  FLOWLOCK_UNLOCK(&f);
551  FAIL;
552  }
553  FLOWLOCK_UNLOCK(&f);
554 
555  /* do detect */
556  SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
557 
558  if (PacketAlertCheck(p3, 1)) {
559  printf("(p3) sig 1 alerted, but it should not have: ");
560  FAIL;
561  }
562  if (!(PacketAlertCheck(p3, 2))) {
563  printf("(p3) sig 2 didn't alert, but it should have: ");
564  FAIL;
565  }
566 
567  if (alp_tctx != NULL)
568  AppLayerParserThreadCtxFree(alp_tctx);
569  if (det_ctx != NULL)
570  DetectEngineThreadCtxDeinit(&tv, det_ctx);
571  if (de_ctx != NULL)
572  SigGroupCleanup(de_ctx);
573  if (de_ctx != NULL)
574  DetectEngineCtxFree(de_ctx);
575 
576  FLOW_DESTROY(&f);
577  UTHFreePacket(p1);
578  UTHFreePacket(p2);
579  UTHFreePacket(p3);
580  PASS;
581 }
582 
583 /** \test simple google.com query matching (TCP) */
584 static int DetectDnsQueryTest03(void)
585 {
586  /* google.com */
587  uint8_t buf[] = { 0x00, 28,
588  0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
589  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
591  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
592  0x00, 0x10, 0x00, 0x01, };
593  Flow f;
594  DNSState *dns_state = NULL;
595  Packet *p = NULL;
596  Signature *s = NULL;
597  ThreadVars tv;
598  DetectEngineThreadCtx *det_ctx = NULL;
599  TcpSession ssn;
601 
602  memset(&tv, 0, sizeof(ThreadVars));
603  memset(&f, 0, sizeof(Flow));
604  memset(&ssn, 0, sizeof(TcpSession));
605 
606  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_TCP,
607  "192.168.1.5", "192.168.1.1",
608  41424, 53);
609 
610  FLOW_INITIALIZE(&f);
611  f.protoctx = (void *)&ssn;
612  f.flags |= FLOW_IPV4;
613  f.proto = IPPROTO_TCP;
615 
616  p->flow = &f;
619  f.alproto = ALPROTO_DNS;
620 
622 
624  FAIL_IF_NULL(de_ctx);
626  de_ctx->flags |= DE_QUIET;
627 
628  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
629  "(msg:\"Test dns_query option\"; "
630  "dns_query; content:\"google\"; nocase; sid:1;)");
631  FAIL_IF_NULL(s);
632 
633  SigGroupBuild(de_ctx);
634  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
635 
636  FLOWLOCK_WRLOCK(&f);
637  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
638  STREAM_TOSERVER, buf, sizeof(buf));
639  if (r != 0) {
640  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
641  FLOWLOCK_UNLOCK(&f);
642  FAIL;
643  }
644  FLOWLOCK_UNLOCK(&f);
645 
646  dns_state = f.alstate;
647  FAIL_IF_NULL(dns_state);
648 
649  /* do detect */
650  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
651 
652  if (!(PacketAlertCheck(p, 1))) {
653  printf("sig 1 didn't alert, but it should have: ");
654  FAIL;
655  }
656 
657  if (alp_tctx != NULL)
658  AppLayerParserThreadCtxFree(alp_tctx);
659  if (det_ctx != NULL)
660  DetectEngineThreadCtxDeinit(&tv, det_ctx);
661  if (de_ctx != NULL)
662  SigGroupCleanup(de_ctx);
663  if (de_ctx != NULL)
664  DetectEngineCtxFree(de_ctx);
665 
667  FLOW_DESTROY(&f);
668  UTHFreePacket(p);
669  PASS;
670 }
671 
672 /** \test simple google.com query matching (TCP splicing) */
673 static int DetectDnsQueryTest04(void)
674 {
675  /* google.com */
676  uint8_t buf1[] = { 0x00, 28,
677  0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
678  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
679  uint8_t buf2[] = { 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
680  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
681  0x00, 0x10, 0x00, 0x01, };
682  Flow f;
683  DNSState *dns_state = NULL;
684  Packet *p1 = NULL, *p2 = NULL;
685  Signature *s = NULL;
686  ThreadVars tv;
687  DetectEngineThreadCtx *det_ctx = NULL;
688  TcpSession ssn;
690 
691  memset(&tv, 0, sizeof(ThreadVars));
692  memset(&f, 0, sizeof(Flow));
693  memset(&ssn, 0, sizeof(TcpSession));
694 
695  p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_TCP,
696  "192.168.1.5", "192.168.1.1",
697  41424, 53);
698  p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_TCP,
699  "192.168.1.5", "192.168.1.1",
700  41424, 53);
701 
702  FLOW_INITIALIZE(&f);
703  f.protoctx = (void *)&ssn;
704  f.flags |= FLOW_IPV4;
705  f.proto = IPPROTO_TCP;
707  f.alproto = ALPROTO_DNS;
708 
709  p1->flow = &f;
712 
713  p2->flow = &f;
715  p2->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED;
716 
718 
720  FAIL_IF_NULL(de_ctx);
722  de_ctx->flags |= DE_QUIET;
723 
724  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
725  "(msg:\"Test dns_query option\"; "
726  "dns_query; content:\"google\"; nocase; sid:1;)");
727  FAIL_IF_NULL(s);
728 
729  SigGroupBuild(de_ctx);
730  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
731 
732  FLOWLOCK_WRLOCK(&f);
733  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
734  STREAM_TOSERVER, buf1, sizeof(buf1));
735  if (r != 0) {
736  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
737  FLOWLOCK_UNLOCK(&f);
738  FAIL;
739  }
740  FLOWLOCK_UNLOCK(&f);
741 
742  dns_state = f.alstate;
743  FAIL_IF_NULL(dns_state);
744 
745  /* do detect */
746  SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
747 
748  if (PacketAlertCheck(p1, 1)) {
749  printf("sig 1 alerted, but it should not have: ");
750  FAIL;
751  }
752 
753  FLOWLOCK_WRLOCK(&f);
754  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
755  buf2, sizeof(buf2));
756  if (r != 0) {
757  printf("toserver chunk 1 returned %" PRId32 ", expected 0\n", r);
758  FLOWLOCK_UNLOCK(&f);
759  FAIL;
760  }
761  FLOWLOCK_UNLOCK(&f);
762 
763  /* do detect */
764  SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
765 
766  if (!(PacketAlertCheck(p2, 1))) {
767  printf("sig 1 didn't alert, but it should have: ");
768  FAIL;
769  }
770 
771  if (alp_tctx != NULL)
772  AppLayerParserThreadCtxFree(alp_tctx);
773  if (det_ctx != NULL)
774  DetectEngineThreadCtxDeinit(&tv, det_ctx);
775  if (de_ctx != NULL)
776  SigGroupCleanup(de_ctx);
777  if (de_ctx != NULL)
778  DetectEngineCtxFree(de_ctx);
779 
781  FLOW_DESTROY(&f);
782  UTHFreePacket(p1);
783  UTHFreePacket(p2);
784  PASS;
785 }
786 
787 /** \test simple google.com query matching (TCP splicing) */
788 static int DetectDnsQueryTest05(void)
789 {
790  /* google.com in 2 chunks (buf1 and buf2) */
791  uint8_t buf1[] = { 0x00, 28, /* len 28 */
792  0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
793  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
794 
795  uint8_t buf2[] = { 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
796  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
797  0x00, 0x10, 0x00, 0x01, };
798 
799  uint8_t buf3[] = { 0x00, 44, /* len 44 */
800  0x10, 0x32, /* tx id */
801  0x81, 0x80, /* flags: resp, recursion desired, recusion available */
802  0x00, 0x01, /* 1 query */
803  0x00, 0x01, /* 1 answer */
804  0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */
805  /* query record */
806  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */
807  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */
808  0x00, 0x01, 0x00, 0x01, /* type a, class in */
809  /* answer */
810  0xc0, 0x0c, /* ref to name in query above */
811  0x00, 0x01, 0x00, 0x01, /* type a, class in */
812  0x00, 0x01, 0x40, 0xef, /* ttl */
813  0x00, 0x04, /* data len */
814  0x01, 0x02, 0x03, 0x04 }; /* addr */
815 
816  /* google.net */
817  uint8_t buf4[] = { 0x00, 28, /* len 28 */
818  0x11, 0x33, 0x01, 0x00, 0x00, 0x01,
819  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
821  0x65, 0x03, 0x6E, 0x65, 0x74, 0x00,
822  0x00, 0x10, 0x00, 0x01, };
823  Flow f;
824  DNSState *dns_state = NULL;
825  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL, *p4 = NULL;
826  Signature *s = NULL;
827  ThreadVars tv;
828  DetectEngineThreadCtx *det_ctx = NULL;
829  TcpSession ssn;
831 
832  memset(&tv, 0, sizeof(ThreadVars));
833  memset(&f, 0, sizeof(Flow));
834  memset(&ssn, 0, sizeof(TcpSession));
835 
836  p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_TCP,
837  "192.168.1.5", "192.168.1.1",
838  41424, 53);
839  p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_TCP,
840  "192.168.1.5", "192.168.1.1",
841  41424, 53);
842  p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_TCP,
843  "192.168.1.5", "192.168.1.1",
844  41424, 53);
845  p4 = UTHBuildPacketReal(buf4, sizeof(buf4), IPPROTO_TCP,
846  "192.168.1.5", "192.168.1.1",
847  41424, 53);
848 
849  FLOW_INITIALIZE(&f);
850  f.protoctx = (void *)&ssn;
851  f.flags |= FLOW_IPV4;
852  f.proto = IPPROTO_TCP;
854  f.alproto = ALPROTO_DNS;
855 
856  p1->flow = &f;
859 
860  p2->flow = &f;
862  p2->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED;
863 
864  p3->flow = &f;
866  p3->flowflags |= FLOW_PKT_TOCLIENT|FLOW_PKT_ESTABLISHED;
867 
868  p4->flow = &f;
870  p4->flowflags |= FLOW_PKT_TOSERVER|FLOW_PKT_ESTABLISHED;
871 
873 
875  FAIL_IF_NULL(de_ctx);
877  de_ctx->flags |= DE_QUIET;
878 
879  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
880  "(msg:\"Test dns_query option\"; "
881  "dns_query; content:\"google.com\"; nocase; sid:1;)");
882  FAIL_IF_NULL(s);
883  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
884  "(msg:\"Test dns_query option\"; "
885  "dns_query; content:\"google.net\"; nocase; sid:2;)");
886  FAIL_IF_NULL(s);
887 
888  SigGroupBuild(de_ctx);
889  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
890 
891  FLOWLOCK_WRLOCK(&f);
892  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
893  STREAM_TOSERVER, buf1, sizeof(buf1));
894  if (r != 0) {
895  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
896  FLOWLOCK_UNLOCK(&f);
897  FAIL;
898  }
899  FLOWLOCK_UNLOCK(&f);
900 
901  dns_state = f.alstate;
902  FAIL_IF_NULL(dns_state);
903 
904  /* do detect */
905  SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
906 
907  if (PacketAlertCheck(p1, 1)) {
908  printf("(p1) sig 1 alerted, but it should not have: ");
909  FAIL;
910  }
911  if (PacketAlertCheck(p1, 2)) {
912  printf("(p1) sig 2 did alert, but it should not have: ");
913  FAIL;
914  }
915 
916  FLOWLOCK_WRLOCK(&f);
917  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
918  buf2, sizeof(buf2));
919  if (r != 0) {
920  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
921  FLOWLOCK_UNLOCK(&f);
922  FAIL;
923  }
924  FLOWLOCK_UNLOCK(&f);
925 
926  /* do detect */
927  SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
928 
929  if (!(PacketAlertCheck(p2, 1))) {
930  printf("sig 1 didn't alert, but it should have: ");
931  FAIL;
932  }
933  if (PacketAlertCheck(p2, 2)) {
934  printf("(p2) sig 2 did alert, but it should not have: ");
935  FAIL;
936  }
937 
938  FLOWLOCK_WRLOCK(&f);
939  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT,
940  buf3, sizeof(buf3));
941  if (r != 0) {
942  printf("toclient chunk 1 returned %" PRId32 ", expected 0: ", r);
943  FLOWLOCK_UNLOCK(&f);
944  FAIL;
945  }
946  FLOWLOCK_UNLOCK(&f);
947 
948  /* do detect */
949  SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
950 
951  if (PacketAlertCheck(p3, 1)) {
952  printf("sig 1 did alert, but it should not have: ");
953  FAIL;
954  }
955  if (PacketAlertCheck(p3, 2)) {
956  printf("(p3) sig 2 did alert, but it should not have: ");
957  FAIL;
958  }
959 
960  FLOWLOCK_WRLOCK(&f);
961  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
962  buf4, sizeof(buf4));
963  if (r != 0) {
964  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
965  FLOWLOCK_UNLOCK(&f);
966  FAIL;
967  }
968  FLOWLOCK_UNLOCK(&f);
969 
970  /* do detect */
971  SigMatchSignatures(&tv, de_ctx, det_ctx, p4);
972 
973  if (PacketAlertCheck(p4, 1)) {
974  printf("(p4) sig 1 did alert, but it should not have: ");
975  FAIL;
976  }
977  if (!(PacketAlertCheck(p4, 2))) {
978  printf("sig 1 didn't alert, but it should have: ");
979  FAIL;
980  }
981 
982  if (alp_tctx != NULL)
983  AppLayerParserThreadCtxFree(alp_tctx);
984  if (det_ctx != NULL)
985  DetectEngineThreadCtxDeinit(&tv, det_ctx);
986  if (de_ctx != NULL)
987  SigGroupCleanup(de_ctx);
988  if (de_ctx != NULL)
989  DetectEngineCtxFree(de_ctx);
990 
992  FLOW_DESTROY(&f);
993  UTHFreePacket(p1);
994  UTHFreePacket(p2);
995  UTHFreePacket(p3);
996  UTHFreePacket(p4);
997  PASS;
998 }
999 
1000 /** \test simple google.com query matching, pcre */
1001 static int DetectDnsQueryTest06(void)
1002 {
1003  /* google.com */
1004  uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1005  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
1007  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
1008  0x00, 0x10, 0x00, 0x01, };
1009  Flow f;
1010  DNSState *dns_state = NULL;
1011  Packet *p = NULL;
1012  Signature *s = NULL;
1013  ThreadVars tv;
1014  DetectEngineThreadCtx *det_ctx = NULL;
1016 
1017  memset(&tv, 0, sizeof(ThreadVars));
1018  memset(&f, 0, sizeof(Flow));
1019 
1020  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP,
1021  "192.168.1.5", "192.168.1.1",
1022  41424, 53);
1023 
1024  FLOW_INITIALIZE(&f);
1025  f.flags |= FLOW_IPV4;
1026  f.proto = IPPROTO_UDP;
1028 
1029  p->flow = &f;
1030  p->flags |= PKT_HAS_FLOW;
1032  f.alproto = ALPROTO_DNS;
1033 
1035  FAIL_IF_NULL(de_ctx);
1036  de_ctx->mpm_matcher = mpm_default_matcher;
1037  de_ctx->flags |= DE_QUIET;
1038 
1039  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
1040  "(msg:\"Test dns_query option\"; "
1041  "dns_query; content:\"google\"; nocase; "
1042  "pcre:\"/google\\.com$/i\"; sid:1;)");
1043  FAIL_IF_NULL(s);
1044  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
1045  "(msg:\"Test dns_query option\"; "
1046  "dns_query; content:\"google\"; nocase; "
1047  "pcre:\"/^\\.[a-z]{2,3}$/iR\"; sid:2;)");
1048  FAIL_IF_NULL(s);
1049 
1050  SigGroupBuild(de_ctx);
1051  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1052 
1053  FLOWLOCK_WRLOCK(&f);
1054  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
1055  STREAM_TOSERVER, buf, sizeof(buf));
1056  if (r != 0) {
1057  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1058  FLOWLOCK_UNLOCK(&f);
1059  FAIL;
1060  }
1061  FLOWLOCK_UNLOCK(&f);
1062 
1063  dns_state = f.alstate;
1064  FAIL_IF_NULL(dns_state);
1065 
1066  /* do detect */
1067  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
1068 
1069  if (!(PacketAlertCheck(p, 1))) {
1070  printf("sig 1 didn't alert, but it should have: ");
1071  FAIL;
1072  }
1073  if (!(PacketAlertCheck(p, 2))) {
1074  printf("sig 2 didn't alert, but it should have: ");
1075  FAIL;
1076  }
1077 
1078  if (alp_tctx != NULL)
1079  AppLayerParserThreadCtxFree(alp_tctx);
1080  if (det_ctx != NULL)
1081  DetectEngineThreadCtxDeinit(&tv, det_ctx);
1082  if (de_ctx != NULL)
1083  SigGroupCleanup(de_ctx);
1084  if (de_ctx != NULL)
1085  DetectEngineCtxFree(de_ctx);
1086 
1087  FLOW_DESTROY(&f);
1088  UTHFreePacket(p);
1089  PASS;
1090 }
1091 
1092 /** \test multi tx google.(com|net) query matching +
1093  * app layer event */
1094 static int DetectDnsQueryTest07(void)
1095 {
1096  /* google.com */
1097  uint8_t buf1[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
1098  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1099  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
1100  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
1101  0x00, 0x01, 0x00, 0x01, };
1102 
1103  uint8_t buf2[] = { 0x10, 0x32, /* tx id */
1104  0x81, 0x80|0x40, /* flags: resp, recursion desired, recusion available */
1105  0x00, 0x01, /* 1 query */
1106  0x00, 0x01, /* 1 answer */
1107  0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */
1108  /* query record */
1109  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */
1110  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */
1111  0x00, 0x01, 0x00, 0x01, /* type a, class in */
1112  /* answer */
1113  0xc0, 0x0c, /* ref to name in query above */
1114  0x00, 0x01, 0x00, 0x01, /* type a, class in */
1115  0x00, 0x01, 0x40, 0xef, /* ttl */
1116  0x00, 0x04, /* data len */
1117  0x01, 0x02, 0x03, 0x04 }; /* addr */
1118 
1119  /* google.net */
1120  uint8_t buf3[] = { 0x11, 0x33, 0x01, 0x00, 0x00, 0x01,
1121  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
1123  0x65, 0x03, 0x6E, 0x65, 0x74, 0x00,
1124  0x00, 0x10, 0x00, 0x01, };
1125  Flow f;
1126  DNSState *dns_state = NULL;
1127  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1128  Signature *s = NULL;
1129  ThreadVars tv;
1130  DetectEngineThreadCtx *det_ctx = NULL;
1132 
1133  memset(&tv, 0, sizeof(ThreadVars));
1134  memset(&f, 0, sizeof(Flow));
1135 
1136  p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
1137  "192.168.1.5", "192.168.1.1",
1138  41424, 53);
1139  p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_UDP,
1140  "192.168.1.5", "192.168.1.1",
1141  41424, 53);
1142  p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_UDP,
1143  "192.168.1.5", "192.168.1.1",
1144  41424, 53);
1145 
1146  FLOW_INITIALIZE(&f);
1147  f.flags |= FLOW_IPV4;
1148  f.proto = IPPROTO_UDP;
1150  f.alproto = ALPROTO_DNS;
1151 
1152  p1->flow = &f;
1153  p1->flags |= PKT_HAS_FLOW;
1155  p1->pcap_cnt = 1;
1156 
1157  p2->flow = &f;
1158  p2->flags |= PKT_HAS_FLOW;
1159  p2->flowflags |= FLOW_PKT_TOCLIENT;
1160  p2->pcap_cnt = 2;
1161 
1162  p3->flow = &f;
1163  p3->flags |= PKT_HAS_FLOW;
1164  p3->flowflags |= FLOW_PKT_TOSERVER;
1165  p3->pcap_cnt = 3;
1166 
1168  FAIL_IF_NULL(de_ctx);
1169  de_ctx->mpm_matcher = mpm_default_matcher;
1170  de_ctx->flags |= DE_QUIET;
1171 
1172  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
1173  "(msg:\"Test dns_query option\"; "
1174  "dns_query; content:\"google.com\"; nocase; sid:1;)");
1175  FAIL_IF_NULL(s);
1176  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
1177  "(msg:\"Test dns_query option\"; "
1178  "dns_query; content:\"google.net\"; nocase; sid:2;)");
1179  FAIL_IF_NULL(s);
1180  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
1181  "(msg:\"Test Z flag event\"; "
1182  "app-layer-event:dns.z_flag_set; sid:3;)");
1183  FAIL_IF_NULL(s);
1184 
1185  SigGroupBuild(de_ctx);
1186  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
1187 
1188  FLOWLOCK_WRLOCK(&f);
1189  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
1190  STREAM_TOSERVER, buf1, sizeof(buf1));
1191  if (r != 0) {
1192  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1193  FLOWLOCK_UNLOCK(&f);
1194  FAIL;
1195  }
1196  FLOWLOCK_UNLOCK(&f);
1197 
1198  dns_state = f.alstate;
1199  FAIL_IF_NULL(dns_state);
1200 
1201  /* do detect */
1202  SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
1203 
1204  if (!(PacketAlertCheck(p1, 1))) {
1205  printf("(p1) sig 1 didn't alert, but it should have: ");
1206  FAIL;
1207  }
1208  if (PacketAlertCheck(p1, 2)) {
1209  printf("(p1) sig 2 did alert, but it should not have: ");
1210  FAIL;
1211  }
1212 
1213  FLOWLOCK_WRLOCK(&f);
1214  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT,
1215  buf2, sizeof(buf2));
1216  if (r != -1) {
1217  printf("toserver client 1 returned %" PRId32 ", expected -1\n", r);
1218  FLOWLOCK_UNLOCK(&f);
1219  FAIL;
1220  }
1221  FLOWLOCK_UNLOCK(&f);
1222 
1223  /* do detect */
1224  SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
1225 
1226  if (PacketAlertCheck(p2, 1)) {
1227  printf("(p2) sig 1 alerted, but it should not have: ");
1228  FAIL;
1229  }
1230  if (PacketAlertCheck(p2, 2)) {
1231  printf("(p2) sig 2 alerted, but it should not have: ");
1232  FAIL;
1233  }
1234  if (!(PacketAlertCheck(p2, 3))) {
1235  printf("(p2) sig 3 didn't alert, but it should have: ");
1236  FAIL;
1237  }
1238 
1239  FLOWLOCK_WRLOCK(&f);
1240  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
1241  buf3, sizeof(buf3));
1242  if (r != 0) {
1243  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
1244  FLOWLOCK_UNLOCK(&f);
1245  FAIL;
1246  }
1247  FLOWLOCK_UNLOCK(&f);
1248 
1249  /* do detect */
1250  SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
1251 
1252  if (PacketAlertCheck(p3, 1)) {
1253  printf("(p3) sig 1 alerted, but it should not have: ");
1254  FAIL;
1255  }
1256  if (!(PacketAlertCheck(p3, 2))) {
1257  printf("(p3) sig 2 didn't alert, but it should have: ");
1258  FAIL;
1259  }
1260  /** \todo should not alert, bug #839
1261  if (PacketAlertCheck(p3, 3)) {
1262  printf("(p3) sig 3 did alert, but it should not have: ");
1263  goto end;
1264  }
1265  */
1266 
1267  if (alp_tctx != NULL)
1268  AppLayerParserThreadCtxFree(alp_tctx);
1269  if (det_ctx != NULL)
1270  DetectEngineThreadCtxDeinit(&tv, det_ctx);
1271  if (de_ctx != NULL)
1272  SigGroupCleanup(de_ctx);
1273  if (de_ctx != NULL)
1274  DetectEngineCtxFree(de_ctx);
1275 
1276  FLOW_DESTROY(&f);
1277  UTHFreePacket(p1);
1278  UTHFreePacket(p2);
1279  UTHFreePacket(p3);
1280  PASS;
1281 }
1282 
1283 static int DetectDnsQueryIsdataatParseTest(void)
1284 {
1286  FAIL_IF_NULL(de_ctx);
1287  de_ctx->flags |= DE_QUIET;
1288 
1289  Signature *s = DetectEngineAppendSig(de_ctx,
1290  "alert dns any any -> any any ("
1291  "dns_query; content:\"one\"; "
1292  "isdataat:!4,relative; sid:1;)");
1293  FAIL_IF_NULL(s);
1294 
1295  SigMatch *sm = s->init_data->smlists_tail[g_dns_query_buffer_id];
1296  FAIL_IF_NULL(sm);
1298 
1299  DetectIsdataatData *data = (DetectIsdataatData *)sm->ctx;
1302  FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
1303 
1304  DetectEngineCtxFree(de_ctx);
1305  PASS;
1306 }
1307 
1308 #endif
1309 
1310 static void DetectDnsQueryRegisterTests(void)
1311 {
1312 #ifdef UNITTESTS
1313  UtRegisterTest("DetectDnsQueryTest01", DetectDnsQueryTest01);
1314  UtRegisterTest("DetectDnsQueryTest02", DetectDnsQueryTest02);
1315  UtRegisterTest("DetectDnsQueryTest03 -- tcp", DetectDnsQueryTest03);
1316  UtRegisterTest("DetectDnsQueryTest04 -- tcp splicing",
1317  DetectDnsQueryTest04);
1318  UtRegisterTest("DetectDnsQueryTest05 -- tcp splicing/multi tx",
1319  DetectDnsQueryTest05);
1320  UtRegisterTest("DetectDnsQueryTest06 -- pcre", DetectDnsQueryTest06);
1321  UtRegisterTest("DetectDnsQueryTest07 -- app layer event",
1322  DetectDnsQueryTest07);
1323 
1324  UtRegisterTest("DetectDnsQueryIsdataatParseTest",
1325  DetectDnsQueryIsdataatParseTest);
1326 #endif
1327 }
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
SignatureInitData * init_data
Definition: detect.h:560
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
int DetectEngineInspectDnsResponse(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
struct Flow_ * flow
Definition: decode.h:444
uint16_t minlen
Definition: util-mpm.h:95
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
uint16_t discontinue_matching
Definition: detect.h:1026
uint8_t proto
Definition: flow.h:346
Per flow DNS state container.
void DetectDnsQueryRegister(void)
Registration function for keyword: dns_query.
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
#define PASS
Pass the test.
one time registration of keywords at start up
Definition: detect.h:567
DNS Transaction, request/reply with same TX id.
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:195
#define ISDATAAT_RELATIVE
Container for matching data for a signature group.
Definition: detect.h:1295
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
uint64_t pcap_cnt
Definition: decode.h:566
uint32_t buffer_offset
Definition: detect.h:991
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
#define ISDATAAT_RAWBYTES
const char * name
Definition: detect.h:1160
Signature container.
Definition: detect.h:492
struct DetectEngineAppInspectionEngine_::@100 v2
#define TRUE
void * protoctx
Definition: flow.h:398
main detection engine ctx
Definition: detect.h:720
struct PrefilterMpmDnsQuery PrefilterMpmDnsQuery
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
void * alstate
Definition: flow.h:436
#define DE_QUIET
Definition: detect.h:298
DNS Query storage. Stored in TX list.
int DetectBufferTypeGetByName(const char *name)
#define str(s)
#define SCCalloc(nm, a)
Definition: util-mem.h:205
#define SIG_FLAG_TOCLIENT
Definition: detect.h:244
uint8_t flags
Definition: detect.h:721
#define DETECT_ENGINE_INSPECT_SIG_MATCH
const MpmCtx * mpm_ctx
uint64_t inspect_offset
Definition: detect.h:351
uint16_t mpm_type
Definition: util-mpm.h:84
void(* Free)(void *)
Definition: detect.h:1151
#define ISDATAAT_NEGATED
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
uint16_t mpm_matcher
Definition: detect.h:769
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1752
#define SIG_FLAG_TOSERVER
Definition: detect.h:243
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
void DetectAppLayerInspectEngineRegister2(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr2 Callback2, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
PrefilterRuleStore pmq
Definition: detect.h:1061
Packet * UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst, uint16_t sport, uint16_t dport)
UTHBuildPacketReal is a function that create tcp/udp packets for unittests specifying ip and port sou...
uint8_t flowflags
Definition: decode.h:438
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
AppProto alproto
Definition: detect.h:496
struct SigMatch_ ** smlists_tail
Definition: detect.h:488
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
int SigGroupCleanup(DetectEngineCtx *de_ctx)
uint8_t type
Definition: detect.h:325
const char * desc
Definition: detect.h:1162
#define FAIL
Definition: util-unittest.h:60
SigMatchCtx * ctx
Definition: detect.h:327
int mpm_default_matcher
Definition: util-mpm.h:166
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.h:165
#define SCFree(a)
Definition: util-mem.h:236
uint16_t tx_id
DetectEngineTransforms transforms
Definition: detect.h:585
void InspectionBufferSetup(InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
MpmThreadCtx mtcu
Definition: detect.h:1059
void InspectionBufferApplyTransforms(InspectionBuffer *buffer, const DetectEngineTransforms *transforms)
#define SIGMATCH_NOOPT
Definition: detect.h:1328
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1129
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, uint8_t *buffer, uint32_t buffer_len, uint32_t stream_start_offset, uint8_t flags, uint8_t inspection_mode, void *data)
Run the actual payload match functions.
struct DetectMpmAppLayerRegistery_::@101 v2
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
struct DNSQueryEntry_ DNSQueryEntry
DNS Query storage. Stored in TX list.
InspectionBufferMultipleForList * InspectionBufferGetMulti(DetectEngineThreadCtx *det_ctx, const int list_id)
int inspection_recursion_counter
Definition: detect.h:1038
#define PKT_HAS_FLOW
Definition: decode.h:1101
#define DETECT_CI_FLAGS_SINGLE
uint32_t inspect_len
Definition: detect.h:350
const DNSQueryEntry * query
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
int DetectBufferSetActiveList(Signature *s, const int list)
const uint8_t * inspect
Definition: detect.h:349
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:158
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, void(*PrefilterTxFunc)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f, void *tx, const uint64_t idx, const uint8_t flags), AppProto alproto, int tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Per thread variable structure.
Definition: threadvars.h:57
const DetectEngineTransforms * transforms
#define FLOW_PKT_TOCLIENT
Definition: flow.h:194
AppProto alproto
application level protocol
Definition: flow.h:407
uint32_t flags
Definition: decode.h:442
InspectionBuffer * InspectionBufferMultipleForListGet(InspectionBufferMultipleForList *fb, uint32_t local_id)
for a InspectionBufferMultipleForList get a InspectionBuffer
uint16_t flags
Definition: detect.h:1154
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
uint8_t protomap
Definition: flow.h:402
Flow data structure.
Definition: flow.h:327
#define FLOW_IPV4
Definition: flow.h:93
uint32_t flags
Definition: flow.h:377
#define PKT_STREAM_EST
Definition: decode.h:1099
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
void(* RegisterTests)(void)
Definition: detect.h:1152
a single match condition for a signature
Definition: detect.h:324
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
const DetectEngineTransforms * transforms
Definition: detect.h:421
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectAppLayerMpmRegister2(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectMpmAppLayerRegistery *mpm_reg, int list_id), InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register a MPM engine
int DetectEngineInspectDnsRequest(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)