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 direction,
54  uint8_t *input, uint32_t len, uint8_t *rdir)
55 {
56  if (len == 0 || len < sizeof(DNSHeader)) {
57  return ALPROTO_UNKNOWN;
58  }
59 
60  // Validate and return ALPROTO_FAILED if needed.
61  if (!rs_dns_probe(input, len)) {
62  return ALPROTO_FAILED;
63  }
64 
65  return ALPROTO_DNS;
66 }
67 
68 static int RustDNSGetAlstateProgress(void *tx, uint8_t direction)
69 {
70  return rs_dns_tx_get_alstate_progress(tx, direction);
71 }
72 
73 static uint64_t RustDNSGetTxCnt(void *alstate)
74 {
75  return rs_dns_state_get_tx_count(alstate);
76 }
77 
78 static void *RustDNSGetTx(void *alstate, uint64_t tx_id)
79 {
80  return rs_dns_state_get_tx(alstate, tx_id);
81 }
82 
83 static void RustDNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
84 {
85  rs_dns_tx_set_logged(alstate, tx, logged);
86 }
87 
88 static LoggerId RustDNSGetTxLogged(void *alstate, void *tx)
89 {
90  return rs_dns_tx_get_logged(alstate, tx);
91 }
92 
93 static void RustDNSStateTransactionFree(void *state, uint64_t tx_id)
94 {
95  rs_dns_state_tx_free(state, tx_id);
96 }
97 
98 static DetectEngineState *RustDNSGetTxDetectState(void *tx)
99 {
100  return rs_dns_state_get_tx_detect_state(tx);
101 }
102 
103 static int RustDNSSetTxDetectState(void *tx, DetectEngineState *s)
104 {
105  rs_dns_state_set_tx_detect_state(tx, s);
106  return 0;
107 }
108 
109 static void RustDNSSetDetectFlags(void *tx, uint8_t dir, uint64_t flags)
110 {
111  rs_dns_tx_set_detect_flags(tx, dir, flags);
112 }
113 
114 static uint64_t RustDNSGetDetectFlags(void *tx, uint8_t dir)
115 {
116  return rs_dns_tx_get_detect_flags(tx, dir);
117 }
118 
119 static AppLayerDecoderEvents *RustDNSGetEvents(void *state, uint64_t id)
120 {
121  return rs_dns_state_get_events(state, id);
122 }
123 
124 void RegisterRustDNSUDPParsers(void)
125 {
126  const char *proto_name = "dns";
127 
128  /** DNS */
129  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
131 
132  if (RunmodeIsUnittests()) {
133  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "53", ALPROTO_DNS, 0,
134  sizeof(DNSHeader), STREAM_TOSERVER, DNSUDPProbe,
135  NULL);
136  } else {
137  int have_cfg = AppLayerProtoDetectPPParseConfPorts("udp",
138  IPPROTO_UDP, proto_name, ALPROTO_DNS, 0, sizeof(DNSHeader),
139  DNSUDPProbe, NULL);
140 
141  /* If no config, enable on port 53. */
142  if (!have_cfg) {
143 #ifndef AFLFUZZ_APPLAYER
144  SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS UDP config found, "
145  "enabling DNS detection on port 53.");
146 #endif
147  AppLayerProtoDetectPPRegister(IPPROTO_UDP, "53", ALPROTO_DNS,
148  0, sizeof(DNSHeader), STREAM_TOSERVER,
149  DNSUDPProbe, NULL);
150  }
151  }
152  } else {
153  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
154  proto_name);
155  return;
156  }
157 
158  if (AppLayerParserConfParserEnabled("udp", proto_name)) {
160  RustDNSUDPParseRequest);
162  RustDNSUDPParseResponse);
164  rs_dns_state_new, rs_dns_state_free);
166  RustDNSStateTransactionFree);
168  RustDNSGetEvents);
170  RustDNSGetTxDetectState, RustDNSSetTxDetectState);
172  RustDNSGetDetectFlags, RustDNSSetDetectFlags);
173 
174  AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_DNS, RustDNSGetTx);
176  RustDNSGetTxCnt);
178  RustDNSGetTxLogged, RustDNSSetTxLogged);
180  RustDNSGetAlstateProgress);
181 
183  rs_dns_state_progress_completion_status);
184 
186 
187 #if 0
188  DNSUDPConfigure();
189 #endif
190  } else {
191  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
192  "still on.", proto_name);
193  }
194 #ifdef UNITTESTS
196  RustDNSUDPParserRegisterTests);
197 #endif
198 }
199 
200 #ifdef UNITTESTS
201 
202 #include "util-unittest-helper.h"
203 
204 static int RustDNSUDPParserTest01 (void)
205 {
206  /* query: abcdefghijk.com
207  * TTL: 86400
208  * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
209  * ns, hostmaster */
210  uint8_t buf[] = { 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
211  0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
212  0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
213  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
214  0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
215  0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
216  0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
217  0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
218  0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
219  0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
220  0x80};
221  size_t buflen = sizeof(buf);
222  Flow *f = NULL;
223 
224  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
225  FAIL_IF_NULL(f);
226  f->proto = IPPROTO_UDP;
227  f->alproto = ALPROTO_DNS;
228  f->alstate = rs_dns_state_new();
229  FAIL_IF_NULL(f->alstate);
230 
231  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
232  NULL, STREAM_START));
233 
234  UTHFreeFlow(f);
235  PASS;
236 }
237 
238 static int RustDNSUDPParserTest02 (void)
239 {
240  uint8_t buf[] = {
241  0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
242  0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
243  0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
244  0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
245  0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
246  0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
247  0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
248  0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
249  0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
250  0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
251  };
252  size_t buflen = sizeof(buf);
253  Flow *f = NULL;
254 
255  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
256  FAIL_IF_NULL(f);
257  f->proto = IPPROTO_UDP;
258  f->alproto = ALPROTO_DNS;
259  f->alstate = rs_dns_state_new();
260  FAIL_IF_NULL(f->alstate);
261 
262  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
263  NULL, STREAM_START));
264 
265  UTHFreeFlow(f);
266  PASS;
267 }
268 
269 static int RustDNSUDPParserTest03 (void)
270 {
271  uint8_t buf[] = {
272  0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
273  0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
274  0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
275  0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
276  0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
277  0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
278  0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
279  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
280  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
281  0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
282  };
283  size_t buflen = sizeof(buf);
284  Flow *f = NULL;
285 
286  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
287  FAIL_IF_NULL(f);
288  f->proto = IPPROTO_UDP;
289  f->alproto = ALPROTO_DNS;
290  f->alstate = rs_dns_state_new();
291  FAIL_IF_NULL(f->alstate);
292 
293  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
294  NULL, STREAM_START));
295 
296  UTHFreeFlow(f);
297  PASS;
298 }
299 
300 /** \test TXT records in answer */
301 static int RustDNSUDPParserTest04 (void)
302 {
303  uint8_t buf[] = {
304  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
305  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
306  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
307  0x01,
308  /* answer record start */
309  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
310  /* txt record starts: */
311  0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
312  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
313  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
314  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
315  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
316  };
317  size_t buflen = sizeof(buf);
318  Flow *f = NULL;
319 
320  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
321  FAIL_IF_NULL(f);
322  f->proto = IPPROTO_UDP;
323  f->alproto = ALPROTO_DNS;
324  f->alstate = rs_dns_state_new();
325  FAIL_IF_NULL(f->alstate);
326 
327  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
328  NULL, STREAM_START));
329 
330  UTHFreeFlow(f);
331  PASS;
332 }
333 
334 /** \test TXT records in answer, bad txtlen */
335 static int RustDNSUDPParserTest05 (void)
336 {
337  uint8_t buf[] = {
338  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
339  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
340  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
341  0x01,
342  /* answer record start */
343  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
344  /* txt record starts: */
345  0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
346  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
347  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
348  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
349  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
350  };
351  size_t buflen = sizeof(buf);
352  Flow *f = NULL;
353 
354  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
355  FAIL_IF_NULL(f);
356  f->proto = IPPROTO_UDP;
357  f->alproto = ALPROTO_DNS;
358  f->alstate = rs_dns_state_new();
359  FAIL_IF_NULL(f->alstate);
360 
361  FAIL_IF(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
362  NULL, STREAM_START) != -1);
363 
364  UTHFreeFlow(f);
365  PASS;
366 }
367 
368 static void RustDNSUDPParserRegisterTests(void)
369 {
370  UtRegisterTest("RustDNSUDPParserTest01", RustDNSUDPParserTest01);
371  UtRegisterTest("RustDNSUDPParserTest02", RustDNSUDPParserTest02);
372  UtRegisterTest("RustDNSUDPParserTest03", RustDNSUDPParserTest03);
373  UtRegisterTest("RustDNSUDPParserTest04", RustDNSUDPParserTest04);
374  UtRegisterTest("RustDNSUDPParserTest05", RustDNSUDPParserTest05);
375 }
376 
377 #endif
378 
379 #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:343
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:433
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:259
#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:404
Flow data structure.
Definition: flow.h:324
#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))