suricata
detect-dns-query.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2023 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 "decode.h"
34 #include "detect.h"
35 
36 #include "detect-parse.h"
37 #include "detect-engine.h"
38 #include "detect-engine-build.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-parser.h"
58 #include "detect-dns-query.h"
59 
60 #include "util-profiling.h"
61 #include "util-unittest-helper.h"
62 #include "rust.h"
63 
64 static int DetectDnsQuerySetup (DetectEngineCtx *, Signature *, const char *);
65 #ifdef UNITTESTS
66 static void DetectDnsQueryRegisterTests(void);
67 #endif
68 static int g_dns_query_buffer_id = 0;
69 
71  uint32_t local_id; /**< used as index into thread inspect array */
72  void *txv;
73 };
74 
75 static InspectionBuffer *DnsQueryGetData(DetectEngineThreadCtx *det_ctx,
76  const DetectEngineTransforms *transforms, Flow *f, struct DnsQueryGetDataArgs *cbdata,
77  int list_id)
78 {
79  SCEnter();
80 
81  InspectionBuffer *buffer =
82  InspectionBufferMultipleForListGet(det_ctx, list_id, cbdata->local_id);
83  if (buffer == NULL)
84  return NULL;
85  if (buffer->initialized)
86  return buffer;
87 
88  const uint8_t *data;
89  uint32_t data_len;
90  if (SCDnsTxGetQueryName(cbdata->txv, false, cbdata->local_id, &data, &data_len) == 0) {
92  return NULL;
93  }
94  InspectionBufferSetupMulti(buffer, transforms, data, data_len);
95  buffer->flags = DETECT_CI_FLAGS_SINGLE;
96 
97  SCReturnPtr(buffer, "InspectionBuffer");
98 }
99 
100 static uint8_t DetectEngineInspectDnsQuery(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
101  const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags,
102  void *alstate, void *txv, uint64_t tx_id)
103 {
104  uint32_t local_id = 0;
105 
106  const DetectEngineTransforms *transforms = NULL;
107  if (!engine->mpm) {
108  transforms = engine->v2.transforms;
109  }
110 
111  while(1) {
112  struct DnsQueryGetDataArgs cbdata = { local_id, txv, };
113  InspectionBuffer *buffer =
114  DnsQueryGetData(det_ctx, transforms, f, &cbdata, engine->sm_list);
115  if (buffer == NULL || buffer->inspect == NULL)
116  break;
117 
118  const bool match = DetectEngineContentInspectionBuffer(de_ctx, det_ctx, s, engine->smd,
120  if (match) {
122  }
123  local_id++;
124  }
126 }
127 
128 typedef struct PrefilterMpmDnsQuery {
129  int list_id;
130  const MpmCtx *mpm_ctx;
133 
134 /** \brief DnsQuery DnsQuery Mpm prefilter callback
135  *
136  * \param det_ctx detection engine thread ctx
137  * \param p packet to inspect
138  * \param f flow to inspect
139  * \param txv tx to inspect
140  * \param pectx inspection context
141  */
142 static void PrefilterTxDnsQuery(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
143  Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
144 {
145  SCEnter();
146 
147  const PrefilterMpmDnsQuery *ctx = (const PrefilterMpmDnsQuery *)pectx;
148  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
149  const int list_id = ctx->list_id;
150 
151  uint32_t local_id = 0;
152  while(1) {
153  // loop until we get a NULL
154 
155  struct DnsQueryGetDataArgs cbdata = { local_id, txv };
156  InspectionBuffer *buffer = DnsQueryGetData(det_ctx, ctx->transforms, f, &cbdata, list_id);
157  if (buffer == NULL)
158  break;
159 
160  if (buffer->inspect_len >= mpm_ctx->minlen) {
161  (void)mpm_table[mpm_ctx->mpm_type].Search(
162  mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
163  PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
164  }
165 
166  local_id++;
167  }
168 }
169 
170 static void PrefilterMpmDnsQueryFree(void *ptr)
171 {
172  SCFree(ptr);
173 }
174 
175 static int PrefilterMpmDnsQueryRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
176  const DetectBufferMpmRegistry *mpm_reg, int list_id)
177 {
178  PrefilterMpmDnsQuery *pectx = SCCalloc(1, sizeof(*pectx));
179  if (pectx == NULL)
180  return -1;
181  pectx->list_id = list_id;
182  pectx->mpm_ctx = mpm_ctx;
183  pectx->transforms = &mpm_reg->transforms;
184 
185  return PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxDnsQuery,
186  mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
187  pectx, PrefilterMpmDnsQueryFree, mpm_reg->pname);
188 }
189 
190 /**
191  * \brief Registration function for keyword: dns_query
192  */
194 {
195  sigmatch_table[DETECT_AL_DNS_QUERY].name = "dns.query";
197  sigmatch_table[DETECT_AL_DNS_QUERY].desc = "sticky buffer to match DNS query-buffer";
198  sigmatch_table[DETECT_AL_DNS_QUERY].url = "/rules/dns-keywords.html#dns-query";
199  sigmatch_table[DETECT_AL_DNS_QUERY].Setup = DetectDnsQuerySetup;
200 #ifdef UNITTESTS
201  sigmatch_table[DETECT_AL_DNS_QUERY].RegisterTests = DetectDnsQueryRegisterTests;
202 #endif
205 
207  "dns_query", SIG_FLAG_TOSERVER, 2, PrefilterMpmDnsQueryRegister, NULL, ALPROTO_DNS, 1);
208 
210  "dns_query", ALPROTO_DNS, SIG_FLAG_TOSERVER, 1, DetectEngineInspectDnsQuery, NULL);
211 
213  "dns request query");
215 
216  g_dns_query_buffer_id = DetectBufferTypeGetByName("dns_query");
217 
218 #ifdef HAVE_LUA
219  /* register these generic engines from here for now */
224 
226  "dns requests");
228  "dns responses");
229 #endif
230 }
231 
232 
233 /**
234  * \brief setup the dns_query sticky buffer keyword used in the rule
235  *
236  * \param de_ctx Pointer to the Detection Engine Context
237  * \param s Pointer to the Signature to which the current keyword belongs
238  * \param str Should hold an empty string always
239  *
240  * \retval 0 On success
241  * \retval -1 On failure
242  */
243 
244 static int DetectDnsQuerySetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
245 {
246  if (DetectBufferSetActiveList(de_ctx, s, g_dns_query_buffer_id) < 0)
247  return -1;
249  return -1;
250  return 0;
251 }
252 
253 #ifdef UNITTESTS
254 #include "detect-isdataat.h"
255 #include "detect-engine-alert.h"
256 
257 /** \test simple google.com query matching */
258 static int DetectDnsQueryTest01(void)
259 {
260  /* google.com */
261  uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
262  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
264  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
265  0x00, 0x10, 0x00, 0x01, };
266  Flow f;
267  void *dns_state = NULL;
268  Packet *p = NULL;
269  Signature *s = NULL;
270  ThreadVars tv;
271  DetectEngineThreadCtx *det_ctx = NULL;
273 
274  memset(&tv, 0, sizeof(ThreadVars));
275  memset(&f, 0, sizeof(Flow));
276 
277  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP,
278  "192.168.1.5", "192.168.1.1",
279  41424, 53);
280 
281  FLOW_INITIALIZE(&f);
282  f.flags |= FLOW_IPV4;
283  f.proto = IPPROTO_UDP;
285 
286  p->flow = &f;
287  p->flags |= PKT_HAS_FLOW;
289  f.alproto = ALPROTO_DNS;
290 
294  de_ctx->flags |= DE_QUIET;
295 
296  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
297  "(msg:\"Test dns_query option\"; "
298  "dns_query; content:\"google\"; nocase; sid:1;)");
299  FAIL_IF_NULL(s);
300 
302  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
303 
304  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
305  STREAM_TOSERVER, buf, sizeof(buf));
306  if (r != 0) {
307  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
308  FAIL;
309  }
310 
311  dns_state = f.alstate;
312  FAIL_IF_NULL(dns_state);
313 
314  /* do detect */
315  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
316 
317  if (!(PacketAlertCheck(p, 1))) {
318  printf("sig 1 didn't alert, but it should have: ");
319  FAIL;
320  }
321 
322  if (alp_tctx != NULL)
324  if (det_ctx != NULL)
325  DetectEngineThreadCtxDeinit(&tv, det_ctx);
326  if (de_ctx != NULL)
328  if (de_ctx != NULL)
330 
331  FLOW_DESTROY(&f);
332  UTHFreePacket(p);
333  PASS;
334 }
335 
336 /** \test multi tx google.(com|net) query matching */
337 static int DetectDnsQueryTest02(void)
338 {
339  /* google.com */
340  uint8_t buf1[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
341  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
343  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
344  0x00, 0x01, 0x00, 0x01, };
345 
346  uint8_t buf2[] = { 0x10, 0x32, /* tx id */
347  0x81, 0x80, /* flags: resp, recursion desired, recursion available */
348  0x00, 0x01, /* 1 query */
349  0x00, 0x01, /* 1 answer */
350  0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */
351  /* query record */
352  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */
353  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */
354  0x00, 0x01, 0x00, 0x01, /* type a, class in */
355  /* answer */
356  0xc0, 0x0c, /* ref to name in query above */
357  0x00, 0x01, 0x00, 0x01, /* type a, class in */
358  0x00, 0x01, 0x40, 0xef, /* ttl */
359  0x00, 0x04, /* data len */
360  0x01, 0x02, 0x03, 0x04 }; /* addr */
361 
362  /* google.net */
363  uint8_t buf3[] = { 0x11, 0x33, 0x01, 0x00, 0x00, 0x01,
364  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
366  0x65, 0x03, 0x6E, 0x65, 0x74, 0x00,
367  0x00, 0x10, 0x00, 0x01, };
368  Flow f;
369  void *dns_state = NULL;
370  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
371  Signature *s = NULL;
372  ThreadVars tv;
373  DetectEngineThreadCtx *det_ctx = NULL;
375 
376  memset(&tv, 0, sizeof(ThreadVars));
377  memset(&f, 0, sizeof(Flow));
378 
379  p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
380  "192.168.1.5", "192.168.1.1",
381  41424, 53);
382  p2 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
383  "192.168.1.5", "192.168.1.1",
384  41424, 53);
385  p3 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
386  "192.168.1.5", "192.168.1.1",
387  41424, 53);
388 
389  FLOW_INITIALIZE(&f);
390  f.flags |= FLOW_IPV4;
391  f.proto = IPPROTO_UDP;
393  f.alproto = ALPROTO_DNS;
394 
395  p1->flow = &f;
396  p1->flags |= PKT_HAS_FLOW;
398  p1->pcap_cnt = 1;
399 
400  p2->flow = &f;
401  p2->flags |= PKT_HAS_FLOW;
402  p2->flowflags |= FLOW_PKT_TOCLIENT;
403  p2->pcap_cnt = 2;
404 
405  p3->flow = &f;
406  p3->flags |= PKT_HAS_FLOW;
407  p3->flowflags |= FLOW_PKT_TOSERVER;
408  p3->pcap_cnt = 3;
409 
413  de_ctx->flags |= DE_QUIET;
414 
415  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
416  "(msg:\"Test dns_query option\"; "
417  "dns_query; content:\"google.com\"; nocase; sid:1;)");
418  FAIL_IF_NULL(s);
419  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
420  "(msg:\"Test dns_query option\"; "
421  "dns_query; content:\"google.net\"; nocase; sid:2;)");
422  FAIL_IF_NULL(s);
423 
425  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
426 
427  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
428  STREAM_TOSERVER, buf1, sizeof(buf1));
429  if (r != 0) {
430  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
431  FAIL;
432  }
433 
434  dns_state = f.alstate;
435  FAIL_IF_NULL(dns_state);
436 
437  /* do detect */
438  SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
439 
440  if (!(PacketAlertCheck(p1, 1))) {
441  printf("(p1) sig 1 didn't alert, but it should have: ");
442  FAIL;
443  }
444  if (PacketAlertCheck(p1, 2)) {
445  printf("(p1) sig 2 did alert, but it should not have: ");
446  FAIL;
447  }
448 
449  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT,
450  buf2, sizeof(buf2));
451  if (r != 0) {
452  printf("toserver client 1 returned %" PRId32 ", expected 0: ", r);
453  FAIL;
454  }
455 
456  /* do detect */
457  SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
458 
459  if (PacketAlertCheck(p2, 1)) {
460  printf("(p2) sig 1 alerted, but it should not have: ");
461  FAIL;
462  }
463  if (PacketAlertCheck(p2, 2)) {
464  printf("(p2) sig 2 alerted, but it should not have: ");
465  FAIL;
466  }
467 
468  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
469  buf3, sizeof(buf3));
470  if (r != 0) {
471  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
472  FAIL;
473  }
474 
475  /* do detect */
476  SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
477 
478  if (PacketAlertCheck(p3, 1)) {
479  printf("(p3) sig 1 alerted, but it should not have: ");
480  FAIL;
481  }
482  if (!(PacketAlertCheck(p3, 2))) {
483  printf("(p3) sig 2 didn't alert, but it should have: ");
484  FAIL;
485  }
486 
487  if (alp_tctx != NULL)
489  if (det_ctx != NULL)
490  DetectEngineThreadCtxDeinit(&tv, det_ctx);
491  if (de_ctx != NULL)
493  if (de_ctx != NULL)
495 
496  FLOW_DESTROY(&f);
497  UTHFreePacket(p1);
498  UTHFreePacket(p2);
499  UTHFreePacket(p3);
500  PASS;
501 }
502 
503 /** \test simple google.com query matching (TCP) */
504 static int DetectDnsQueryTest03(void)
505 {
506  /* google.com */
507  uint8_t buf[] = { 0x00, 28,
508  0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
509  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
511  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
512  0x00, 0x10, 0x00, 0x01, };
513  Flow f;
514  void *dns_state = NULL;
515  Packet *p = NULL;
516  Signature *s = NULL;
517  ThreadVars tv;
518  DetectEngineThreadCtx *det_ctx = NULL;
519  TcpSession ssn;
521 
522  memset(&tv, 0, sizeof(ThreadVars));
523  memset(&f, 0, sizeof(Flow));
524  memset(&ssn, 0, sizeof(TcpSession));
525 
526  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_TCP,
527  "192.168.1.5", "192.168.1.1",
528  41424, 53);
529 
530  FLOW_INITIALIZE(&f);
531  f.protoctx = (void *)&ssn;
532  f.flags |= FLOW_IPV4;
533  f.proto = IPPROTO_TCP;
535 
536  p->flow = &f;
539  f.alproto = ALPROTO_DNS;
540 
541  StreamTcpInitConfig(true);
542 
546  de_ctx->flags |= DE_QUIET;
547 
548  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
549  "(msg:\"Test dns_query option\"; "
550  "dns_query; content:\"google\"; nocase; sid:1;)");
551  FAIL_IF_NULL(s);
552 
554  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
555 
556  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
557  STREAM_TOSERVER, buf, sizeof(buf));
558  if (r != 0) {
559  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
560  FAIL;
561  }
562 
563  dns_state = f.alstate;
564  FAIL_IF_NULL(dns_state);
565 
566  /* do detect */
567  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
568 
569  if (!(PacketAlertCheck(p, 1))) {
570  printf("sig 1 didn't alert, but it should have: ");
571  FAIL;
572  }
573 
574  if (alp_tctx != NULL)
576  if (det_ctx != NULL)
577  DetectEngineThreadCtxDeinit(&tv, det_ctx);
578  if (de_ctx != NULL)
580  if (de_ctx != NULL)
582 
583  StreamTcpFreeConfig(true);
584  FLOW_DESTROY(&f);
585  UTHFreePacket(p);
586  PASS;
587 }
588 
589 
590 /** \test simple google.com query matching, pcre */
591 static int DetectDnsQueryTest04(void)
592 {
593  /* google.com */
594  uint8_t buf[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
595  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
597  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
598  0x00, 0x10, 0x00, 0x01, };
599  Flow f;
600  void *dns_state = NULL;
601  Packet *p = NULL;
602  Signature *s = NULL;
603  ThreadVars tv;
604  DetectEngineThreadCtx *det_ctx = NULL;
606 
607  memset(&tv, 0, sizeof(ThreadVars));
608  memset(&f, 0, sizeof(Flow));
609 
610  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_UDP,
611  "192.168.1.5", "192.168.1.1",
612  41424, 53);
613 
614  FLOW_INITIALIZE(&f);
615  f.flags |= FLOW_IPV4;
616  f.proto = IPPROTO_UDP;
618 
619  p->flow = &f;
620  p->flags |= PKT_HAS_FLOW;
622  f.alproto = ALPROTO_DNS;
623 
627  de_ctx->flags |= DE_QUIET;
628 
629  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
630  "(msg:\"Test dns_query option\"; "
631  "dns_query; content:\"google\"; nocase; "
632  "pcre:\"/google\\.com$/i\"; sid:1;)");
633  FAIL_IF_NULL(s);
634  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
635  "(msg:\"Test dns_query option\"; "
636  "dns_query; content:\"google\"; nocase; "
637  "pcre:\"/^\\.[a-z]{2,3}$/iR\"; sid:2;)");
638  FAIL_IF_NULL(s);
639 
641  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
642 
643  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
644  STREAM_TOSERVER, buf, sizeof(buf));
645  if (r != 0) {
646  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
647  FAIL;
648  }
649 
650  dns_state = f.alstate;
651  FAIL_IF_NULL(dns_state);
652 
653  /* do detect */
654  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
655 
656  if (!(PacketAlertCheck(p, 1))) {
657  printf("sig 1 didn't alert, but it should have: ");
658  FAIL;
659  }
660  if (!(PacketAlertCheck(p, 2))) {
661  printf("sig 2 didn't alert, but it should have: ");
662  FAIL;
663  }
664 
665  if (alp_tctx != NULL)
667  if (det_ctx != NULL)
668  DetectEngineThreadCtxDeinit(&tv, det_ctx);
669  if (de_ctx != NULL)
671  if (de_ctx != NULL)
673 
674  FLOW_DESTROY(&f);
675  UTHFreePacket(p);
676  PASS;
677 }
678 
679 /** \test multi tx google.(com|net) query matching +
680  * app layer event */
681 static int DetectDnsQueryTest05(void)
682 {
683  /* google.com */
684  uint8_t buf1[] = { 0x10, 0x32, 0x01, 0x00, 0x00, 0x01,
685  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
687  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00,
688  0x00, 0x01, 0x00, 0x01, };
689 
690  uint8_t buf2[] = { 0x10, 0x32, /* tx id */
691  0x81, 0x80|0x40, /* flags: resp, recursion desired, recursion available */
692  0x00, 0x01, /* 1 query */
693  0x00, 0x01, /* 1 answer */
694  0x00, 0x00, 0x00, 0x00, /* no auth rr, additional rr */
695  /* query record */
696  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C, /* name */
697  0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, /* name cont */
698  0x00, 0x01, 0x00, 0x01, /* type a, class in */
699  /* answer */
700  0xc0, 0x0c, /* ref to name in query above */
701  0x00, 0x01, 0x00, 0x01, /* type a, class in */
702  0x00, 0x01, 0x40, 0xef, /* ttl */
703  0x00, 0x04, /* data len */
704  0x01, 0x02, 0x03, 0x04 }; /* addr */
705 
706  /* google.net */
707  uint8_t buf3[] = { 0x11, 0x33, 0x01, 0x00, 0x00, 0x01,
708  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709  0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6C,
710  0x65, 0x03, 0x6E, 0x65, 0x74, 0x00,
711  0x00, 0x10, 0x00, 0x01, };
712  Flow f;
713  void *dns_state = NULL;
714  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
715  Signature *s = NULL;
716  ThreadVars tv;
717  DetectEngineThreadCtx *det_ctx = NULL;
719 
720  memset(&tv, 0, sizeof(ThreadVars));
721  memset(&f, 0, sizeof(Flow));
722 
723  p1 = UTHBuildPacketReal(buf1, sizeof(buf1), IPPROTO_UDP,
724  "192.168.1.5", "192.168.1.1",
725  41424, 53);
726  p2 = UTHBuildPacketReal(buf2, sizeof(buf2), IPPROTO_UDP,
727  "192.168.1.5", "192.168.1.1",
728  41424, 53);
729  p3 = UTHBuildPacketReal(buf3, sizeof(buf3), IPPROTO_UDP,
730  "192.168.1.5", "192.168.1.1",
731  41424, 53);
732 
733  FLOW_INITIALIZE(&f);
734  f.flags |= FLOW_IPV4;
735  f.proto = IPPROTO_UDP;
737  f.alproto = ALPROTO_DNS;
738 
739  p1->flow = &f;
740  p1->flags |= PKT_HAS_FLOW;
742  p1->pcap_cnt = 1;
743 
744  p2->flow = &f;
745  p2->flags |= PKT_HAS_FLOW;
746  p2->flowflags |= FLOW_PKT_TOCLIENT;
747  p2->pcap_cnt = 2;
748 
749  p3->flow = &f;
750  p3->flags |= PKT_HAS_FLOW;
751  p3->flowflags |= FLOW_PKT_TOSERVER;
752  p3->pcap_cnt = 3;
753 
757  de_ctx->flags |= DE_QUIET;
758 
759  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
760  "(msg:\"Test dns_query option\"; "
761  "dns_query; content:\"google.com\"; nocase; sid:1;)");
762  FAIL_IF_NULL(s);
763  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
764  "(msg:\"Test dns_query option\"; "
765  "dns_query; content:\"google.net\"; nocase; sid:2;)");
766  FAIL_IF_NULL(s);
767  s = DetectEngineAppendSig(de_ctx, "alert dns any any -> any any "
768  "(msg:\"Test Z flag event\"; "
769  "app-layer-event:dns.z_flag_set; sid:3;)");
770  FAIL_IF_NULL(s);
771 
773  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
774 
775  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS,
776  STREAM_TOSERVER, buf1, sizeof(buf1));
777  if (r != 0) {
778  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
779  FAIL;
780  }
781 
782  dns_state = f.alstate;
783  FAIL_IF_NULL(dns_state);
784 
785  /* do detect */
786  SigMatchSignatures(&tv, de_ctx, det_ctx, p1);
787 
788  if (!(PacketAlertCheck(p1, 1))) {
789  printf("(p1) sig 1 didn't alert, but it should have: ");
790  FAIL;
791  }
792  if (PacketAlertCheck(p1, 2)) {
793  printf("(p1) sig 2 did alert, but it should not have: ");
794  FAIL;
795  }
796 
797  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOCLIENT,
798  buf2, sizeof(buf2));
799  if (r != 0) {
800  printf("toserver client 1 returned %" PRId32 ", expected 0\n", r);
801  FAIL;
802  }
803 
804  /* do detect */
805  SigMatchSignatures(&tv, de_ctx, det_ctx, p2);
806 
807  if (PacketAlertCheck(p2, 1)) {
808  printf("(p2) sig 1 alerted, but it should not have: ");
809  FAIL;
810  }
811  if (PacketAlertCheck(p2, 2)) {
812  printf("(p2) sig 2 alerted, but it should not have: ");
813  FAIL;
814  }
815  if (!(PacketAlertCheck(p2, 3))) {
816  printf("(p2) sig 3 didn't alert, but it should have: ");
817  FAIL;
818  }
819 
820  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_DNS, STREAM_TOSERVER,
821  buf3, sizeof(buf3));
822  if (r != 0) {
823  printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
824  FAIL;
825  }
826 
827  /* do detect */
828  SigMatchSignatures(&tv, de_ctx, det_ctx, p3);
829 
830  if (PacketAlertCheck(p3, 1)) {
831  printf("(p3) sig 1 alerted, but it should not have: ");
832  FAIL;
833  }
834  if (!(PacketAlertCheck(p3, 2))) {
835  printf("(p3) sig 2 didn't alert, but it should have: ");
836  FAIL;
837  }
838  /** \todo should not alert, bug #839
839  if (PacketAlertCheck(p3, 3)) {
840  printf("(p3) sig 3 did alert, but it should not have: ");
841  goto end;
842  }
843  */
844 
845  if (alp_tctx != NULL)
847  if (det_ctx != NULL)
848  DetectEngineThreadCtxDeinit(&tv, det_ctx);
849  if (de_ctx != NULL)
851  if (de_ctx != NULL)
853 
854  FLOW_DESTROY(&f);
855  UTHFreePacket(p1);
856  UTHFreePacket(p2);
857  UTHFreePacket(p3);
858  PASS;
859 }
860 
861 static void DetectDnsQueryRegisterTests(void)
862 {
863  UtRegisterTest("DetectDnsQueryTest01", DetectDnsQueryTest01);
864  UtRegisterTest("DetectDnsQueryTest02", DetectDnsQueryTest02);
865  UtRegisterTest("DetectDnsQueryTest03 -- tcp", DetectDnsQueryTest03);
866  UtRegisterTest("DetectDnsQueryTest04 -- pcre", DetectDnsQueryTest04);
867  UtRegisterTest("DetectDnsQueryTest05 -- app layer event", DetectDnsQueryTest05);
868 }
869 #endif
DetectEngineAppInspectionEngine_
Definition: detect.h:427
SigTableElmt_::url
const char * url
Definition: detect.h:1299
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1753
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:431
detect-content.h
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:90
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SIGMATCH_INFO_STICKY_BUFFER
#define SIGMATCH_INFO_STICKY_BUFFER
Definition: detect.h:1500
SigTableElmt_::desc
const char * desc
Definition: detect.h:1298
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1022
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
SigTableElmt_::name
const char * name
Definition: detect.h:1296
InspectionBuffer::initialized
bool initialized
Definition: detect.h:378
stream-tcp.h
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1448
DetectEngineTransforms
Definition: detect.h:409
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DnsQueryGetDataArgs::local_id
uint32_t local_id
Definition: detect-dns-query.c:71
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:607
detect-isdataat.h
Flow_::proto
uint8_t proto
Definition: flow.h:373
DetectBufferSetActiveList
int DetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
Definition: detect-engine.c:1335
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:141
InspectionBuffer
Definition: detect.h:374
Packet_::flags
uint32_t flags
Definition: decode.h:474
DnsQueryGetDataArgs::txv
void * txv
Definition: detect-dns-query.c:72
threads.h
Flow_
Flow data structure.
Definition: flow.h:351
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1204
Flow_::protomap
uint8_t protomap
Definition: flow.h:445
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1290
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:839
DetectBufferTypeSupportsMultiInstance
void DetectBufferTypeSupportsMultiInstance(const char *name)
Definition: detect-engine.c:1022
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2533
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:312
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:223
rust.h
DetectBufferMpmRegistry_
one time registration of keywords at start up
Definition: detect.h:680
DE_QUIET
#define DE_QUIET
Definition: detect.h:324
mpm_default_matcher
uint8_t mpm_default_matcher
Definition: util-mpm.c:48
InspectionBuffer::flags
uint8_t flags
Definition: detect.h:379
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1895
DetectBufferMpmRegistry_::app_v2
struct DetectBufferMpmRegistry_::@88::@90 app_v2
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2620
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:468
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:267
UTHBuildPacketReal
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...
Definition: util-unittest-helper.c:244
Flow_::protoctx
void * protoctx
Definition: flow.h:441
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1281
detect-pcre.h
DetectBufferMpmRegistry_::transforms
DetectEngineTransforms transforms
Definition: detect.h:693
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:97
detect-engine-prefilter.h
util-unittest.h
util-unittest-helper.h
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1072
detect-dns-query.h
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:433
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:463
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:266
InspectionBufferSetupMultiEmpty
void InspectionBufferSetupMultiEmpty(InspectionBuffer *buffer)
setup the buffer empty
Definition: detect-engine.c:1546
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1095
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:22
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_MATCH
Definition: detect-engine-state.h:38
DetectEngineCtx_::mpm_matcher
uint8_t mpm_matcher
Definition: detect.h:842
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
Definition: detect-engine-content-inspection.h:36
DetectAppLayerMpmRegister
void DetectAppLayerMpmRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register a MPM engine
Definition: detect-engine-mpm.c:89
app-layer-parser.h
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:99
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2218
util-profiling.h
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:97
Packet_
Definition: decode.h:437
detect-engine-build.h
detect-engine-alert.h
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:168
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:224
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@85 v2
DetectEngineThreadCtx_::mtc
MpmThreadCtx mtc
Definition: detect.h:1203
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2149
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:291
detect-engine-content-inspection.h
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:444
AppLayerTxData
struct AppLayerTxData AppLayerTxData
Definition: detect.h:1358
PREFILTER_PROFILING_ADD_BYTES
#define PREFILTER_PROFILING_ADD_BYTES(det_ctx, bytes)
Definition: util-profiling.h:287
Packet_::flow
struct Flow_ * flow
Definition: decode.h:476
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3244
DETECT_CI_FLAGS_SINGLE
#define DETECT_CI_FLAGS_SINGLE
Definition: detect-engine-content-inspection.h:49
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:794
flags
uint8_t flags
Definition: decode-gre.h:0
SigTableElmt_::alias
const char * alias
Definition: detect.h:1297
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1292
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3454
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:127
util-spm.h
InspectionBufferSetupMulti
void InspectionBufferSetupMulti(InspectionBuffer *buffer, const DetectEngineTransforms *transforms, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1559
PrefilterAppendTxEngine
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterTxFn PrefilterTxFunc, AppProto alproto, int tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:270
DetectEngineInspectGenericList
uint8_t DetectEngineInspectGenericList(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Definition: detect-engine.c:2079
PrefilterMpmDnsQuery::transforms
const DetectEngineTransforms * transforms
Definition: detect-dns-query.c:131
DetectDnsQueryRegister
void DetectDnsQueryRegister(void)
Registration function for keyword: dns_query.
Definition: detect-dns-query.c:193
DETECT_ENGINE_INSPECT_SIG_NO_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
Definition: detect-engine-state.h:37
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:377
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:375
str
#define str(s)
Definition: suricata-common.h:291
SCFree
#define SCFree(p)
Definition: util-mem.h:61
UTHFreePacket
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:448
Flow_::alstate
void * alstate
Definition: flow.h:476
Flow_::flags
uint32_t flags
Definition: flow.h:421
detect-parse.h
Signature_
Signature container.
Definition: detect.h:596
FAIL
#define FAIL
Fail a test.
Definition: util-unittest.h:60
DetectEngineAppInspectionEngine_::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:441
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:225
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2494
PrefilterMpmDnsQuery::mpm_ctx
const MpmCtx * mpm_ctx
Definition: detect-dns-query.c:130
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
DETECT_AL_DNS_QUERY
@ DETECT_AL_DNS_QUERY
Definition: detect-engine-register.h:231
DnsQueryGetDataArgs
Definition: detect-dns-query.c:70
InspectionBufferMultipleForListGet
InspectionBuffer * InspectionBufferMultipleForListGet(DetectEngineThreadCtx *det_ctx, const int list_id, const uint32_t local_id)
for a InspectionBufferMultipleForList get a InspectionBuffer
Definition: detect-engine.c:1499
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1476
DetectAppLayerInspectEngineRegister
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
Definition: detect-engine.c:169
DetectEngineContentInspectionBuffer
bool DetectEngineContentInspectionBuffer(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const InspectionBuffer *b, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
Definition: detect-engine-content-inspection.c:747
PrefilterMpmDnsQuery
Definition: detect-dns-query.c:128
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:841
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:65
DetectBufferTypeSetDescriptionByName
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
Definition: detect-engine.c:1169
MpmCtx_
Definition: util-mpm.h:88
TcpSession_
Definition: stream-tcp-private.h:283
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
PrefilterMpmDnsQuery::list_id
int list_id
Definition: detect-dns-query.c:129
flow-var.h
PrefilterMpmDnsQuery
struct PrefilterMpmDnsQuery PrefilterMpmDnsQuery
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1019
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1288
app-layer.h
DetectBufferMpmRegistry_::pname
char pname[32]
Definition: detect.h:682