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 *tx)
120 {
121  return rs_dns_state_get_events(tx);
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 
187 
188 #if 0
189  DNSUDPConfigure();
190 #endif
191  } else {
192  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
193  "still on.", proto_name);
194  }
195 #ifdef UNITTESTS
197  RustDNSUDPParserRegisterTests);
198 #endif
199 }
200 
201 #ifdef UNITTESTS
202 
203 #include "util-unittest-helper.h"
204 
205 static int RustDNSUDPParserTest01 (void)
206 {
207  /* query: abcdefghijk.com
208  * TTL: 86400
209  * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
210  * ns, hostmaster */
211  uint8_t buf[] = { 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
212  0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
213  0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
214  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
215  0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
216  0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
217  0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
218  0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
219  0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
220  0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
221  0x80};
222  size_t buflen = sizeof(buf);
223  Flow *f = NULL;
224 
225  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
226  FAIL_IF_NULL(f);
227  f->proto = IPPROTO_UDP;
228  f->alproto = ALPROTO_DNS;
229  f->alstate = rs_dns_state_new();
230  FAIL_IF_NULL(f->alstate);
231 
232  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
233  NULL, STREAM_START));
234 
235  UTHFreeFlow(f);
236  PASS;
237 }
238 
239 static int RustDNSUDPParserTest02 (void)
240 {
241  uint8_t buf[] = {
242  0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
243  0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
244  0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
245  0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
246  0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
247  0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
248  0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
249  0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
250  0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
251  0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
252  };
253  size_t buflen = sizeof(buf);
254  Flow *f = NULL;
255 
256  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
257  FAIL_IF_NULL(f);
258  f->proto = IPPROTO_UDP;
259  f->alproto = ALPROTO_DNS;
260  f->alstate = rs_dns_state_new();
261  FAIL_IF_NULL(f->alstate);
262 
263  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
264  NULL, STREAM_START));
265 
266  UTHFreeFlow(f);
267  PASS;
268 }
269 
270 static int RustDNSUDPParserTest03 (void)
271 {
272  uint8_t buf[] = {
273  0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
274  0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
275  0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
276  0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
277  0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
278  0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
279  0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
280  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
281  0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
282  0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
283  };
284  size_t buflen = sizeof(buf);
285  Flow *f = NULL;
286 
287  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
288  FAIL_IF_NULL(f);
289  f->proto = IPPROTO_UDP;
290  f->alproto = ALPROTO_DNS;
291  f->alstate = rs_dns_state_new();
292  FAIL_IF_NULL(f->alstate);
293 
294  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
295  NULL, STREAM_START));
296 
297  UTHFreeFlow(f);
298  PASS;
299 }
300 
301 /** \test TXT records in answer */
302 static int RustDNSUDPParserTest04 (void)
303 {
304  uint8_t buf[] = {
305  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
306  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
307  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
308  0x01,
309  /* answer record start */
310  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
311  /* txt record starts: */
312  0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
313  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
314  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
315  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
316  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
317  };
318  size_t buflen = sizeof(buf);
319  Flow *f = NULL;
320 
321  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
322  FAIL_IF_NULL(f);
323  f->proto = IPPROTO_UDP;
324  f->alproto = ALPROTO_DNS;
325  f->alstate = rs_dns_state_new();
326  FAIL_IF_NULL(f->alstate);
327 
328  FAIL_IF_NOT(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
329  NULL, STREAM_START));
330 
331  UTHFreeFlow(f);
332  PASS;
333 }
334 
335 /** \test TXT records in answer, bad txtlen */
336 static int RustDNSUDPParserTest05 (void)
337 {
338  uint8_t buf[] = {
339  0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
340  0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
341  0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
342  0x01,
343  /* answer record start */
344  0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
345  /* txt record starts: */
346  0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
347  0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
348  0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
349  0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
350  0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
351  };
352  size_t buflen = sizeof(buf);
353  Flow *f = NULL;
354 
355  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
356  FAIL_IF_NULL(f);
357  f->proto = IPPROTO_UDP;
358  f->alproto = ALPROTO_DNS;
359  f->alstate = rs_dns_state_new();
360  FAIL_IF_NULL(f->alstate);
361 
362  FAIL_IF(RustDNSUDPParseResponse(f, f->alstate, NULL, buf, buflen,
363  NULL, STREAM_START) != -1);
364 
365  UTHFreeFlow(f);
366  PASS;
367 }
368 
369 static void RustDNSUDPParserRegisterTests(void)
370 {
371  UtRegisterTest("RustDNSUDPParserTest01", RustDNSUDPParserTest01);
372  UtRegisterTest("RustDNSUDPParserTest02", RustDNSUDPParserTest02);
373  UtRegisterTest("RustDNSUDPParserTest03", RustDNSUDPParserTest03);
374  UtRegisterTest("RustDNSUDPParserTest04", RustDNSUDPParserTest04);
375  UtRegisterTest("RustDNSUDPParserTest05", RustDNSUDPParserTest05);
376 }
377 
378 #endif
379 
380 #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:344
LoggerId
void DNSAppLayerRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto)
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 AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *))
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
void * alstate
Definition: flow.h:438
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 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:409
Flow data structure.
Definition: flow.h:325
#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))