suricata
app-layer-dns-udp-rust.c
Go to the documentation of this file.
1 /* Copyright (C) 2017 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 #include "suricata-common.h"
19 #include "suricata.h"
20 
21 #include "app-layer-protos.h"
22 #include "app-layer-detect-proto.h"
23 #include "app-layer-parser.h"
24 #include "app-layer-dns-common.h"
25 
26 #include "util-unittest.h"
27 
28 #ifdef HAVE_RUST
29 
30 #include "app-layer-dns-udp-rust.h"
31 #include "rust-dns-dns-gen.h"
32 
33 #ifdef UNITTESTS
34 static void RustDNSUDPParserRegisterTests(void);
35 #endif
36 
37 static int RustDNSUDPParseRequest(Flow *f, void *state,
38  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
39  void *local_data, const uint8_t flags)
40 {
41  return rs_dns_parse_request(f, state, pstate, input, input_len,
42  local_data);
43 }
44 
45 static int RustDNSUDPParseResponse(Flow *f, void *state,
46  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
47  void *local_data, const uint8_t flags)
48 {
49  return rs_dns_parse_response(f, state, pstate, input, input_len,
50  local_data);
51 }
52 
53 static uint16_t DNSUDPProbe(Flow *f, uint8_t *input, uint32_t len)
54 {
55  if (len == 0 || len < sizeof(DNSHeader)) {
56  return ALPROTO_UNKNOWN;
57  }
58 
59  // Validate and return ALPROTO_FAILED if needed.
60  if (!rs_dns_probe(input, len)) {
61  return ALPROTO_FAILED;
62  }
63 
64  return ALPROTO_DNS;
65 }
66 
67 static int RustDNSGetAlstateProgress(void *tx, uint8_t direction)
68 {
69  return rs_dns_tx_get_alstate_progress(tx, direction);
70 }
71 
72 static uint64_t RustDNSGetTxCnt(void *alstate)
73 {
74  return rs_dns_state_get_tx_count(alstate);
75 }
76 
77 static void *RustDNSGetTx(void *alstate, uint64_t tx_id)
78 {
79  return rs_dns_state_get_tx(alstate, tx_id);
80 }
81 
82 static void RustDNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
83 {
84  rs_dns_tx_set_logged(alstate, tx, logged);
85 }
86 
87 static LoggerId RustDNSGetTxLogged(void *alstate, void *tx)
88 {
89  return rs_dns_tx_get_logged(alstate, tx);
90 }
91 
92 static void RustDNSStateTransactionFree(void *state, uint64_t tx_id)
93 {
94  rs_dns_state_tx_free(state, tx_id);
95 }
96 
97 static DetectEngineState *RustDNSGetTxDetectState(void *tx)
98 {
99  return rs_dns_state_get_tx_detect_state(tx);
100 }
101 
102 static int RustDNSSetTxDetectState(void *tx, DetectEngineState *s)
103 {
104  rs_dns_state_set_tx_detect_state(tx, s);
105  return 0;
106 }
107 
108 static void RustDNSSetDetectFlags(void *tx, uint8_t dir, uint64_t flags)
109 {
110  rs_dns_tx_set_detect_flags(tx, dir, flags);
111 }
112 
113 static uint64_t RustDNSGetDetectFlags(void *tx, uint8_t dir)
114 {
115  return rs_dns_tx_get_detect_flags(tx, dir);
116 }
117 
118 static AppLayerDecoderEvents *RustDNSGetEvents(void *state, uint64_t id)
119 {
120  return rs_dns_state_get_events(state, id);
121 }
122 
123 void RegisterRustDNSUDPParsers(void)
124 {
125  const char *proto_name = "dns";
126 
127  /** DNS */
128  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
130 
131  if (RunmodeIsUnittests()) {
132  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "53", ALPROTO_DNS, 0,
133  sizeof(DNSHeader), STREAM_TOSERVER, DNSUDPProbe,
134  NULL);
135  } else {
136  int have_cfg = AppLayerProtoDetectPPParseConfPorts("udp",
137  IPPROTO_UDP, proto_name, ALPROTO_DNS, 0, sizeof(DNSHeader),
138  DNSUDPProbe, NULL);
139 
140  /* If no config, enable on port 53. */
141  if (!have_cfg) {
142 #ifndef AFLFUZZ_APPLAYER
143  SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS UDP config found, "
144  "enabling DNS detection on port 53.");
145 #endif
146  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "53", ALPROTO_DNS,
147  0, sizeof(DNSHeader), STREAM_TOSERVER,
148  DNSUDPProbe, NULL);
149  }
150  }
151  } else {
152  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
153  proto_name);
154  return;
155  }
156 
157  if (AppLayerParserConfParserEnabled("udp", proto_name)) {
159  RustDNSUDPParseRequest);
161  RustDNSUDPParseResponse);
163  rs_dns_state_new, rs_dns_state_free);
165  RustDNSStateTransactionFree);
167  RustDNSGetEvents);
169  RustDNSGetTxDetectState, RustDNSSetTxDetectState);
171  RustDNSGetDetectFlags, RustDNSSetDetectFlags);
172 
173  AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_DNS, RustDNSGetTx);
175  RustDNSGetTxCnt);
177  RustDNSGetTxLogged, RustDNSSetTxLogged);
179  RustDNSGetAlstateProgress);
180 
182  rs_dns_state_progress_completion_status);
183 
185 
186 #if 0
187  DNSUDPConfigure();
188 #endif
189  } else {
190  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
191  "still on.", proto_name);
192  }
193 #ifdef UNITTESTS
195  RustDNSUDPParserRegisterTests);
196 #endif
197 }
198 
199 #ifdef UNITTESTS
200 
201 #include "util-unittest-helper.h"
202 
203 static int RustDNSUDPParserTest01 (void)
204 {
205  /* query: abcdefghijk.com
206  * TTL: 86400
207  * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
208  * ns, hostmaster */
209  uint8_t buf[] = { 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
210  0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
211  0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
212  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
213  0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
214  0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
215  0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
216  0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
217  0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
218  0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
219  0x80};
220  size_t buflen = sizeof(buf);
221  Flow *f = NULL;
222 
223  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
224  FAIL_IF_NULL(f);
225  f->proto = IPPROTO_UDP;
226  f->alproto = ALPROTO_DNS;
227  f->alstate = rs_dns_state_new();
228  FAIL_IF_NULL(f->alstate);
229 
230  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
231  NULL, STREAM_START));
232 
233  UTHFreeFlow(f);
234  PASS;
235 }
236 
237 static int RustDNSUDPParserTest02 (void)
238 {
239  uint8_t buf[] = {
240  0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
241  0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
242  0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
243  0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
244  0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
245  0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
246  0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
247  0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
248  0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
249  0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
250  };
251  size_t buflen = sizeof(buf);
252  Flow *f = NULL;
253 
254  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
255  FAIL_IF_NULL(f);
256  f->proto = IPPROTO_UDP;
257  f->alproto = ALPROTO_DNS;
258  f->alstate = rs_dns_state_new();
259  FAIL_IF_NULL(f->alstate);
260 
261  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
262  NULL, STREAM_START));
263 
264  UTHFreeFlow(f);
265  PASS;
266 }
267 
268 static int RustDNSUDPParserTest03 (void)
269 {
270  uint8_t buf[] = {
271  0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
272  0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
273  0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
274  0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
275  0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
276  0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
277  0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
278  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
279  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
280  0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
281  };
282  size_t buflen = sizeof(buf);
283  Flow *f = NULL;
284 
285  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
286  FAIL_IF_NULL(f);
287  f->proto = IPPROTO_UDP;
288  f->alproto = ALPROTO_DNS;
289  f->alstate = rs_dns_state_new();
290  FAIL_IF_NULL(f->alstate);
291 
292  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
293  NULL, STREAM_START));
294 
295  UTHFreeFlow(f);
296  PASS;
297 }
298 
299 /** \test TXT records in answer */
300 static int RustDNSUDPParserTest04 (void)
301 {
302  uint8_t buf[] = {
303  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
304  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
305  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
306  0x01,
307  /* answer record start */
308  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
309  /* txt record starts: */
310  0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
311  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
312  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
313  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
314  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
315  };
316  size_t buflen = sizeof(buf);
317  Flow *f = NULL;
318 
319  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
320  FAIL_IF_NULL(f);
321  f->proto = IPPROTO_UDP;
322  f->alproto = ALPROTO_DNS;
323  f->alstate = rs_dns_state_new();
324  FAIL_IF_NULL(f->alstate);
325 
326  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
327  NULL, STREAM_START));
328 
329  UTHFreeFlow(f);
330  PASS;
331 }
332 
333 /** \test TXT records in answer, bad txtlen */
334 static int RustDNSUDPParserTest05 (void)
335 {
336  uint8_t buf[] = {
337  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
338  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
339  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
340  0x01,
341  /* answer record start */
342  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
343  /* txt record starts: */
344  0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
345  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
346  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
347  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
348  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
349  };
350  size_t buflen = sizeof(buf);
351  Flow *f = NULL;
352 
353  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
354  FAIL_IF_NULL(f);
355  f->proto = IPPROTO_UDP;
356  f->alproto = ALPROTO_DNS;
357  f->alstate = rs_dns_state_new();
358  FAIL_IF_NULL(f->alstate);
359 
360  FAIL_IF(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
361  NULL, STREAM_START) != -1);
362 
363  UTHFreeFlow(f);
364  PASS;
365 }
366 
367 static void RustDNSUDPParserRegisterTests(void)
368 {
369  UtRegisterTest("RustDNSUDPParserTest01", RustDNSUDPParserTest01);
370  UtRegisterTest("RustDNSUDPParserTest02", RustDNSUDPParserTest02);
371  UtRegisterTest("RustDNSUDPParserTest03", RustDNSUDPParserTest03);
372  UtRegisterTest("RustDNSUDPParserTest04", RustDNSUDPParserTest04);
373  UtRegisterTest("RustDNSUDPParserTest05", RustDNSUDPParserTest05);
374 }
375 
376 #endif
377 
378 #endif /* HAVE_RUST */
uint16_t flags
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
uint8_t proto
Definition: flow.h:346
LoggerId
int logged
#define PASS
Pass the test.
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir), void(*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
void RegisterRustDNSUDPParsers(void)
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
void * alstate
Definition: flow.h:436
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests and when...
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
Data structure to store app layer decoder events.
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define STREAM_TOCLIENT
Definition: stream.h:32
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
int RunmodeIsUnittests(void)
Definition: suricata.c:261
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
uint16_t tx_id
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
#define STREAM_START
Definition: stream.h:29
#define STREAM_TOSERVER
Definition: stream.h:31
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
uint8_t len
AppProto alproto
application level protocol
Definition: flow.h:407
Flow data structure.
Definition: flow.h:327
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
void UTHFreeFlow(Flow *flow)
void DNSAppLayerRegisterGetEventInfo(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))