]> git.ipfire.org Git - people/ms/suricata.git/blob - rust/src/dns/dns.rs
applayer: add flags to parser registration struct
[people/ms/suricata.git] / rust / src / dns / dns.rs
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 extern crate nom;
19
20 use std;
21 use std::ffi::CString;
22 use std::mem::transmute;
23 use std::collections::HashMap;
24 use std::collections::VecDeque;
25
26 use crate::log::*;
27 use crate::applayer::*;
28 use crate::core::{self, AppProto, ALPROTO_UNKNOWN, IPPROTO_UDP, IPPROTO_TCP};
29 use crate::dns::parser;
30
31 use nom::IResult;
32 use nom::number::streaming::be_u16;
33
34 /// DNS record types.
35 pub const DNS_RECORD_TYPE_A : u16 = 1;
36 pub const DNS_RECORD_TYPE_NS : u16 = 2;
37 pub const DNS_RECORD_TYPE_MD : u16 = 3; // Obsolete
38 pub const DNS_RECORD_TYPE_MF : u16 = 4; // Obsolete
39 pub const DNS_RECORD_TYPE_CNAME : u16 = 5;
40 pub const DNS_RECORD_TYPE_SOA : u16 = 6;
41 pub const DNS_RECORD_TYPE_MB : u16 = 7; // Experimental
42 pub const DNS_RECORD_TYPE_MG : u16 = 8; // Experimental
43 pub const DNS_RECORD_TYPE_MR : u16 = 9; // Experimental
44 pub const DNS_RECORD_TYPE_NULL : u16 = 10; // Experimental
45 pub const DNS_RECORD_TYPE_WKS : u16 = 11;
46 pub const DNS_RECORD_TYPE_PTR : u16 = 12;
47 pub const DNS_RECORD_TYPE_HINFO : u16 = 13;
48 pub const DNS_RECORD_TYPE_MINFO : u16 = 14;
49 pub const DNS_RECORD_TYPE_MX : u16 = 15;
50 pub const DNS_RECORD_TYPE_TXT : u16 = 16;
51 pub const DNS_RECORD_TYPE_RP : u16 = 17;
52 pub const DNS_RECORD_TYPE_AFSDB : u16 = 18;
53 pub const DNS_RECORD_TYPE_X25 : u16 = 19;
54 pub const DNS_RECORD_TYPE_ISDN : u16 = 20;
55 pub const DNS_RECORD_TYPE_RT : u16 = 21;
56 pub const DNS_RECORD_TYPE_NSAP : u16 = 22;
57 pub const DNS_RECORD_TYPE_NSAPPTR : u16 = 23;
58 pub const DNS_RECORD_TYPE_SIG : u16 = 24;
59 pub const DNS_RECORD_TYPE_KEY : u16 = 25;
60 pub const DNS_RECORD_TYPE_PX : u16 = 26;
61 pub const DNS_RECORD_TYPE_GPOS : u16 = 27;
62 pub const DNS_RECORD_TYPE_AAAA : u16 = 28;
63 pub const DNS_RECORD_TYPE_LOC : u16 = 29;
64 pub const DNS_RECORD_TYPE_NXT : u16 = 30; // Obsolete
65 pub const DNS_RECORD_TYPE_SRV : u16 = 33;
66 pub const DNS_RECORD_TYPE_ATMA : u16 = 34;
67 pub const DNS_RECORD_TYPE_NAPTR : u16 = 35;
68 pub const DNS_RECORD_TYPE_KX : u16 = 36;
69 pub const DNS_RECORD_TYPE_CERT : u16 = 37;
70 pub const DNS_RECORD_TYPE_A6 : u16 = 38; // Obsolete
71 pub const DNS_RECORD_TYPE_DNAME : u16 = 39;
72 pub const DNS_RECORD_TYPE_OPT : u16 = 41;
73 pub const DNS_RECORD_TYPE_APL : u16 = 42;
74 pub const DNS_RECORD_TYPE_DS : u16 = 43;
75 pub const DNS_RECORD_TYPE_SSHFP : u16 = 44;
76 pub const DNS_RECORD_TYPE_IPSECKEY : u16 = 45;
77 pub const DNS_RECORD_TYPE_RRSIG : u16 = 46;
78 pub const DNS_RECORD_TYPE_NSEC : u16 = 47;
79 pub const DNS_RECORD_TYPE_DNSKEY : u16 = 48;
80 pub const DNS_RECORD_TYPE_DHCID : u16 = 49;
81 pub const DNS_RECORD_TYPE_NSEC3 : u16 = 50;
82 pub const DNS_RECORD_TYPE_NSEC3PARAM : u16 = 51;
83 pub const DNS_RECORD_TYPE_TLSA : u16 = 52;
84 pub const DNS_RECORD_TYPE_HIP : u16 = 55;
85 pub const DNS_RECORD_TYPE_CDS : u16 = 59;
86 pub const DNS_RECORD_TYPE_CDNSKEY : u16 = 60;
87 pub const DNS_RECORD_TYPE_SPF : u16 = 99; // Obsolete
88 pub const DNS_RECORD_TYPE_TKEY : u16 = 249;
89 pub const DNS_RECORD_TYPE_TSIG : u16 = 250;
90 pub const DNS_RECORD_TYPE_MAILA : u16 = 254; // Obsolete
91 pub const DNS_RECORD_TYPE_ANY : u16 = 255;
92 pub const DNS_RECORD_TYPE_URI : u16 = 256;
93
94 /// DNS error codes.
95 pub const DNS_RCODE_NOERROR: u16 = 0;
96 pub const DNS_RCODE_FORMERR: u16 = 1;
97 pub const DNS_RCODE_SERVFAIL: u16 = 2;
98 pub const DNS_RCODE_NXDOMAIN: u16 = 3;
99 pub const DNS_RCODE_NOTIMP: u16 = 4;
100 pub const DNS_RCODE_REFUSED: u16 = 5;
101 pub const DNS_RCODE_YXDOMAIN: u16 = 6;
102 pub const DNS_RCODE_YXRRSET: u16 = 7;
103 pub const DNS_RCODE_NXRRSET: u16 = 8;
104 pub const DNS_RCODE_NOTAUTH: u16 = 9;
105 pub const DNS_RCODE_NOTZONE: u16 = 10;
106 // Support for OPT RR from RFC6891 will be needed to
107 // parse RCODE values over 15
108 pub const DNS_RCODE_BADVERS: u16 = 16;
109 pub const DNS_RCODE_BADSIG: u16 = 16;
110 pub const DNS_RCODE_BADKEY: u16 = 17;
111 pub const DNS_RCODE_BADTIME: u16 = 18;
112 pub const DNS_RCODE_BADMODE: u16 = 19;
113 pub const DNS_RCODE_BADNAME: u16 = 20;
114 pub const DNS_RCODE_BADALG: u16 = 21;
115 pub const DNS_RCODE_BADTRUNC: u16 = 22;
116
117
118 /// The maximum number of transactions to keep in the queue pending
119 /// processing before they are aggressively purged. Due to the
120 /// stateless nature of this parser this is rarely needed, especially
121 /// when one call to parse a request parses and a single request, and
122 /// likewise for responses.
123 ///
124 /// Where this matters is when one TCP buffer contains multiple
125 /// requests are responses and one call into the parser creates
126 /// multiple transactions. In this case we have to hold onto
127 /// transactions longer than until handling the next transaction so it
128 /// gets logged.
129 const MAX_TRANSACTIONS: usize = 32;
130
131 static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN;
132
133 #[repr(u32)]
134 pub enum DNSEvent {
135 MalformedData = 0,
136 NotRequest = 1,
137 NotResponse = 2,
138 ZFlagSet = 3,
139 }
140
141 impl DNSEvent {
142 pub fn to_cstring(&self) -> &str {
143 match *self {
144 DNSEvent::MalformedData => "MALFORMED_DATA\0",
145 DNSEvent::NotRequest => "NOT_A_REQUEST\0",
146 DNSEvent::NotResponse => "NOT_A_RESPONSE\0",
147 DNSEvent::ZFlagSet => "Z_FLAG_SET\0",
148 }
149 }
150
151 pub fn from_id(id: u32) -> Option<DNSEvent> {
152 match id {
153 0 => Some(DNSEvent::MalformedData),
154 1 => Some(DNSEvent::NotRequest),
155 2 => Some(DNSEvent::NotResponse),
156 4 => Some(DNSEvent::ZFlagSet),
157 _ => None,
158 }
159 }
160
161 pub fn from_string(s: &str) -> Option<DNSEvent> {
162 match s.to_lowercase().as_ref() {
163 "malformed_data" => Some(DNSEvent::MalformedData),
164 "not_a_request" => Some(DNSEvent::NotRequest),
165 "not_a_response" => Some(DNSEvent::NotRequest),
166 "z_flag_set" => Some(DNSEvent::ZFlagSet),
167 _ => None
168 }
169 }
170 }
171
172 #[no_mangle]
173 pub extern "C" fn rs_dns_state_get_event_info_by_id(
174 event_id: std::os::raw::c_int,
175 event_name: *mut *const std::os::raw::c_char,
176 event_type: *mut core::AppLayerEventType,
177 ) -> i8 {
178 if let Some(e) = DNSEvent::from_id(event_id as u32) {
179 unsafe {
180 *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
181 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
182 }
183 return 0;
184 }
185 return -1;
186 }
187
188 #[no_mangle]
189 pub extern "C" fn rs_dns_state_get_event_info(
190 event_name: *const std::os::raw::c_char,
191 event_id: *mut std::os::raw::c_int,
192 event_type: *mut core::AppLayerEventType
193 ) -> std::os::raw::c_int {
194 if event_name == std::ptr::null() {
195 return -1;
196 }
197
198 let event_name = unsafe { std::ffi::CStr::from_ptr(event_name) };
199 if let Ok(event_name) = event_name.to_str() {
200 if let Some(event) = DNSEvent::from_string(event_name) {
201 unsafe {
202 *event_id = event as std::os::raw::c_int;
203 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
204 }
205 } else {
206 // Unknown event...
207 return -1;
208 }
209 } else {
210 // UTF-8 conversion failed. Should not happen.
211 return -1;
212 }
213
214 return 0;
215 }
216
217 #[derive(Debug,PartialEq)]
218 #[repr(C)]
219 pub struct DNSHeader {
220 pub tx_id: u16,
221 pub flags: u16,
222 pub questions: u16,
223 pub answer_rr: u16,
224 pub authority_rr: u16,
225 pub additional_rr: u16,
226 }
227
228 #[derive(Debug)]
229 pub struct DNSQueryEntry {
230 pub name: Vec<u8>,
231 pub rrtype: u16,
232 pub rrclass: u16,
233 }
234
235 #[derive(Debug,PartialEq)]
236 pub struct DNSAnswerEntry {
237 pub name: Vec<u8>,
238 pub rrtype: u16,
239 pub rrclass: u16,
240 pub ttl: u32,
241 pub data: Vec<u8>,
242 }
243
244 #[derive(Debug)]
245 pub struct DNSRequest {
246 pub header: DNSHeader,
247 pub queries: Vec<DNSQueryEntry>,
248 }
249
250 #[derive(Debug)]
251 pub struct DNSResponse {
252 pub header: DNSHeader,
253 pub queries: Vec<DNSQueryEntry>,
254 pub answers: Vec<DNSAnswerEntry>,
255 pub authorities: Vec<DNSAnswerEntry>,
256 }
257
258 #[derive(Debug)]
259 pub struct DNSTransaction {
260 pub id: u64,
261 pub request: Option<DNSRequest>,
262 pub response: Option<DNSResponse>,
263 pub de_state: Option<*mut core::DetectEngineState>,
264 pub events: *mut core::AppLayerDecoderEvents,
265 pub tx_data: AppLayerTxData,
266 }
267
268 impl DNSTransaction {
269
270 pub fn new() -> DNSTransaction {
271 return DNSTransaction{
272 id: 0,
273 request: None,
274 response: None,
275 de_state: None,
276 events: std::ptr::null_mut(),
277 tx_data: AppLayerTxData::new(),
278 }
279 }
280
281 pub fn free(&mut self) {
282 if self.events != std::ptr::null_mut() {
283 core::sc_app_layer_decoder_events_free_events(&mut self.events);
284 }
285 match self.de_state {
286 Some(state) => {
287 core::sc_detect_engine_state_free(state);
288 }
289 None => { },
290 }
291 }
292
293 /// Get the DNS transactions ID (not the internal tracking ID).
294 pub fn tx_id(&self) -> u16 {
295 if let &Some(ref request) = &self.request {
296 return request.header.tx_id;
297 }
298 if let &Some(ref response) = &self.response {
299 return response.header.tx_id;
300 }
301
302 // Shouldn't happen.
303 return 0;
304 }
305
306 /// Get the reply code of the transaction. Note that this will
307 /// also return 0 if there is no reply.
308 pub fn rcode(&self) -> u16 {
309 if let &Some(ref response) = &self.response {
310 return response.header.flags & 0x000f;
311 }
312 return 0;
313 }
314
315 }
316
317 impl Drop for DNSTransaction {
318 fn drop(&mut self) {
319 self.free();
320 }
321 }
322
323 struct ConfigTracker {
324 map: HashMap<u16, AppLayerTxConfig>,
325 queue: VecDeque<u16>,
326 }
327
328 impl ConfigTracker {
329 fn new() -> ConfigTracker {
330 ConfigTracker {
331 map: HashMap::new(),
332 queue: VecDeque::new(),
333 }
334 }
335
336 fn add(&mut self, id: u16, config: AppLayerTxConfig) {
337 // If at size limit, remove the oldest entry.
338 if self.queue.len() > 499 {
339 if let Some(id) = self.queue.pop_front() {
340 self.map.remove(&id);
341 }
342 }
343
344 self.map.insert(id, config);
345 self.queue.push_back(id);
346 }
347
348 fn remove(&mut self, id: &u16) -> Option<AppLayerTxConfig> {
349 self.map.remove(id)
350 }
351 }
352
353 pub struct DNSState {
354 // Internal transaction ID.
355 pub tx_id: u64,
356
357 // Transactions.
358 pub transactions: Vec<DNSTransaction>,
359
360 pub events: u16,
361
362 pub request_buffer: Vec<u8>,
363 pub response_buffer: Vec<u8>,
364
365 config: Option<ConfigTracker>,
366
367 gap: bool,
368 }
369
370 impl DNSState {
371
372 pub fn new() -> DNSState {
373 return DNSState{
374 tx_id: 0,
375 transactions: Vec::new(),
376 events: 0,
377 request_buffer: Vec::new(),
378 response_buffer: Vec::new(),
379 config: None,
380 gap: false,
381 };
382 }
383
384 /// Allocate a new state with capacites in the buffers for
385 /// potentially buffering as might be needed in TCP.
386 pub fn new_tcp() -> DNSState {
387 return DNSState{
388 tx_id: 0,
389 transactions: Vec::new(),
390 events: 0,
391 request_buffer: Vec::with_capacity(0xffff),
392 response_buffer: Vec::with_capacity(0xffff),
393 config: None,
394 gap: false,
395 };
396 }
397
398 pub fn new_tx(&mut self) -> DNSTransaction {
399 let mut tx = DNSTransaction::new();
400 self.tx_id += 1;
401 tx.id = self.tx_id;
402 return tx;
403 }
404
405 pub fn free_tx(&mut self, tx_id: u64) {
406 let len = self.transactions.len();
407 let mut found = false;
408 let mut index = 0;
409 for i in 0..len {
410 let tx = &self.transactions[i];
411 if tx.id == tx_id + 1 {
412 found = true;
413 index = i;
414 break;
415 }
416 }
417 if found {
418 self.transactions.remove(index);
419 }
420 }
421
422 // Purges all transactions except one. This is a stateless parser
423 // so we don't need to hang onto old transactions.
424 //
425 // This is to actually handle an edge case where a DNS flood
426 // occurs in a single direction with no response packets. In such
427 // a case the functions to free a transaction are never called by
428 // the app-layer as they require bidirectional traffic.
429 pub fn purge(&mut self, tx_id: u64) {
430 while self.transactions.len() > MAX_TRANSACTIONS {
431 if self.transactions[0].id == tx_id + 1 {
432 return;
433 }
434 SCLogDebug!("Purging DNS TX with ID {}", self.transactions[0].id);
435 self.transactions.remove(0);
436 }
437 }
438
439 pub fn get_tx(&mut self, tx_id: u64) -> Option<&DNSTransaction> {
440 SCLogDebug!("get_tx: tx_id={}", tx_id);
441 self.purge(tx_id);
442 for tx in &mut self.transactions {
443 if tx.id == tx_id + 1 {
444 SCLogDebug!("Found DNS TX with ID {}", tx_id);
445 return Some(tx);
446 }
447 }
448 SCLogDebug!("Failed to find DNS TX with ID {}", tx_id);
449 return None;
450 }
451
452 /// Set an event. The event is set on the most recent transaction.
453 pub fn set_event(&mut self, event: DNSEvent) {
454 let len = self.transactions.len();
455 if len == 0 {
456 return;
457 }
458
459 let tx = &mut self.transactions[len - 1];
460 core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events,
461 event as u8);
462 self.events += 1;
463 }
464
465 pub fn parse_request(&mut self, input: &[u8]) -> bool {
466 match parser::dns_parse_request(input) {
467 Ok((_, request)) => {
468 if request.header.flags & 0x8000 != 0 {
469 SCLogDebug!("DNS message is not a request");
470 self.set_event(DNSEvent::NotRequest);
471 return false;
472 }
473
474 if request.header.flags & 0x0040 != 0 {
475 SCLogDebug!("Z-flag set on DNS response");
476 self.set_event(DNSEvent::ZFlagSet);
477 return false;
478 }
479
480 let mut tx = self.new_tx();
481 tx.request = Some(request);
482 self.transactions.push(tx);
483 return true;
484 }
485 Err(nom::Err::Incomplete(_)) => {
486 // Insufficient data.
487 SCLogDebug!("Insufficient data while parsing DNS request");
488 self.set_event(DNSEvent::MalformedData);
489 return false;
490 }
491 Err(_) => {
492 // Error, probably malformed data.
493 SCLogDebug!("An error occurred while parsing DNS request");
494 self.set_event(DNSEvent::MalformedData);
495 return false;
496 }
497 }
498 }
499
500 pub fn parse_response(&mut self, input: &[u8]) -> bool {
501 match parser::dns_parse_response(input) {
502 Ok((_, response)) => {
503
504 SCLogDebug!("Response header flags: {}", response.header.flags);
505
506 if response.header.flags & 0x8000 == 0 {
507 SCLogDebug!("DNS message is not a response");
508 self.set_event(DNSEvent::NotResponse);
509 }
510
511 if response.header.flags & 0x0040 != 0 {
512 SCLogDebug!("Z-flag set on DNS response");
513 self.set_event(DNSEvent::ZFlagSet);
514 return false;
515 }
516
517 let mut tx = self.new_tx();
518 if let Some(ref mut config) = &mut self.config {
519 if let Some(config) = config.remove(&response.header.tx_id) {
520 tx.tx_data.config = config;
521 }
522 }
523 tx.response = Some(response);
524 self.transactions.push(tx);
525 return true;
526 }
527 Err(nom::Err::Incomplete(_)) => {
528 // Insufficient data.
529 SCLogDebug!("Insufficient data while parsing DNS response");
530 self.set_event(DNSEvent::MalformedData);
531 return false;
532 }
533 Err(_) => {
534 // Error, probably malformed data.
535 SCLogDebug!("An error occurred while parsing DNS response");
536 self.set_event(DNSEvent::MalformedData);
537 return false;
538 }
539 }
540 }
541
542 /// TCP variation of response request parser to handle the length
543 /// prefix as well as buffering.
544 ///
545 /// Always buffer and read from the buffer. Should optimize to skip
546 /// the buffer if not needed.
547 ///
548 /// Returns the number of messages parsed.
549 pub fn parse_request_tcp(&mut self, input: &[u8]) -> i8 {
550 if self.gap {
551 let (is_dns, _, is_incomplete) = probe_tcp(input);
552 if is_dns || is_incomplete{
553 self.gap = false;
554 } else {
555 return 0
556 }
557 }
558
559 self.request_buffer.extend_from_slice(input);
560
561 let mut count = 0;
562 while self.request_buffer.len() > 0 {
563 let size = match be_u16(&self.request_buffer) as IResult<&[u8],_> {
564 Ok((_, len)) => i32::from(len),
565 _ => 0
566 } as usize;
567 SCLogDebug!("Have {} bytes, need {} to parse",
568 self.request_buffer.len(), size);
569 if size > 0 && self.request_buffer.len() >= size + 2 {
570 let msg: Vec<u8> = self.request_buffer.drain(0..(size + 2))
571 .collect();
572 if self.parse_request(&msg[2..]) {
573 count += 1
574 }
575 } else {
576 SCLogDebug!("Not enough DNS traffic to parse.");
577 break;
578 }
579 }
580 return count;
581 }
582
583 /// TCP variation of the response parser to handle the length
584 /// prefix as well as buffering.
585 ///
586 /// Always buffer and read from the buffer. Should optimize to skip
587 /// the buffer if not needed.
588 ///
589 /// Returns the number of messages parsed.
590 pub fn parse_response_tcp(&mut self, input: &[u8]) -> i8 {
591 if self.gap {
592 let (is_dns, _, is_incomplete) = probe_tcp(input);
593 if is_dns || is_incomplete{
594 self.gap = false;
595 } else {
596 return 0
597 }
598 }
599
600 self.response_buffer.extend_from_slice(input);
601
602 let mut count = 0;
603 while self.response_buffer.len() > 0 {
604 let size = match be_u16(&self.response_buffer) as IResult<&[u8],_> {
605 Ok((_, len)) => i32::from(len),
606 _ => 0
607 } as usize;
608 if size > 0 && self.response_buffer.len() >= size + 2 {
609 let msg: Vec<u8> = self.response_buffer.drain(0..(size + 2))
610 .collect();
611 if self.parse_response(&msg[2..]) {
612 count += 1;
613 }
614 } else {
615 break;
616 }
617 }
618 return count;
619 }
620
621 /// A gap has been seen in the request direction. Set the gap flag
622 /// to clear any buffered data.
623 pub fn request_gap(&mut self, gap: u32) {
624 if gap > 0 {
625 self.request_buffer.clear();
626 self.gap = true;
627 }
628 }
629
630 /// A gap has been seen in the response direction. Set the gap
631 /// flag to clear any buffered data.
632 pub fn response_gap(&mut self, gap: u32) {
633 if gap > 0 {
634 self.response_buffer.clear();
635 self.gap = true;
636 }
637 }
638 }
639
640 /// Probe input to see if it looks like DNS.
641 fn probe(input: &[u8]) -> (bool, bool) {
642 match parser::dns_parse_request(input) {
643 Ok((_, request)) => {
644 let is_request = request.header.flags & 0x8000 == 0;
645 return (true, is_request);
646 },
647 Err(_) => (false, false),
648 }
649 }
650
651 /// Probe TCP input to see if it looks like DNS.
652 pub fn probe_tcp(input: &[u8]) -> (bool, bool, bool) {
653 match be_u16(input) as IResult<&[u8],_> {
654 Ok((rem, _)) => {
655 let r = probe(rem);
656 return (r.0, r.1, false);
657 },
658 Err(nom::Err::Incomplete(_)) => {
659 return (false, false, true);
660 }
661 _ => {}
662 }
663 return (false, false, false);
664 }
665
666 /// Returns *mut DNSState
667 #[no_mangle]
668 pub extern "C" fn rs_dns_state_new() -> *mut std::os::raw::c_void {
669 let state = DNSState::new();
670 let boxed = Box::new(state);
671 return unsafe{transmute(boxed)};
672 }
673
674 /// Returns *mut DNSState
675 #[no_mangle]
676 pub extern "C" fn rs_dns_state_tcp_new() -> *mut std::os::raw::c_void {
677 let state = DNSState::new_tcp();
678 let boxed = Box::new(state);
679 return unsafe{transmute(boxed)};
680 }
681
682 /// Params:
683 /// - state: *mut DNSState as void pointer
684 #[no_mangle]
685 pub extern "C" fn rs_dns_state_free(state: *mut std::os::raw::c_void) {
686 // Just unbox...
687 let _drop: Box<DNSState> = unsafe{transmute(state)};
688 }
689
690 #[no_mangle]
691 pub extern "C" fn rs_dns_state_tx_free(state: *mut std::os::raw::c_void,
692 tx_id: u64)
693 {
694 let state = cast_pointer!(state, DNSState);
695 state.free_tx(tx_id);
696 }
697
698 /// C binding parse a DNS request. Returns 1 on success, -1 on failure.
699 #[no_mangle]
700 pub extern "C" fn rs_dns_parse_request(_flow: *const core::Flow,
701 state: *mut std::os::raw::c_void,
702 _pstate: *mut std::os::raw::c_void,
703 input: *const u8,
704 input_len: u32,
705 _data: *const std::os::raw::c_void,
706 _flags: u8)
707 -> AppLayerResult {
708 let state = cast_pointer!(state, DNSState);
709 let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
710 if state.parse_request(buf) {
711 AppLayerResult::ok()
712 } else {
713 AppLayerResult::err()
714 }
715 }
716
717 #[no_mangle]
718 pub extern "C" fn rs_dns_parse_response(_flow: *const core::Flow,
719 state: *mut std::os::raw::c_void,
720 _pstate: *mut std::os::raw::c_void,
721 input: *const u8,
722 input_len: u32,
723 _data: *const std::os::raw::c_void,
724 _flags: u8)
725 -> AppLayerResult {
726 let state = cast_pointer!(state, DNSState);
727 let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
728 if state.parse_response(buf) {
729 AppLayerResult::ok()
730 } else {
731 AppLayerResult::err()
732 }
733 }
734
735 /// C binding parse a DNS request. Returns 1 on success, -1 on failure.
736 #[no_mangle]
737 pub extern "C" fn rs_dns_parse_request_tcp(_flow: *const core::Flow,
738 state: *mut std::os::raw::c_void,
739 _pstate: *mut std::os::raw::c_void,
740 input: *const u8,
741 input_len: u32,
742 _data: *const std::os::raw::c_void,
743 _flags: u8)
744 -> AppLayerResult {
745 let state = cast_pointer!(state, DNSState);
746 if input_len > 0 {
747 if input != std::ptr::null_mut() {
748 let buf = unsafe{
749 std::slice::from_raw_parts(input, input_len as usize)};
750 let _ = state.parse_request_tcp(buf);
751 return AppLayerResult::ok();
752 }
753 state.request_gap(input_len);
754 }
755 AppLayerResult::ok()
756 }
757
758 #[no_mangle]
759 pub extern "C" fn rs_dns_parse_response_tcp(_flow: *const core::Flow,
760 state: *mut std::os::raw::c_void,
761 _pstate: *mut std::os::raw::c_void,
762 input: *const u8,
763 input_len: u32,
764 _data: *const std::os::raw::c_void,
765 _flags: u8)
766 -> AppLayerResult {
767 let state = cast_pointer!(state, DNSState);
768 if input_len > 0 {
769 if input != std::ptr::null_mut() {
770 let buf = unsafe{
771 std::slice::from_raw_parts(input, input_len as usize)};
772 let _ = state.parse_response_tcp(buf);
773 return AppLayerResult::ok();
774 }
775 state.response_gap(input_len);
776 }
777 AppLayerResult::ok()
778 }
779
780 #[no_mangle]
781 pub extern "C" fn rs_dns_state_progress_completion_status(
782 _direction: u8)
783 -> std::os::raw::c_int
784 {
785 SCLogDebug!("rs_dns_state_progress_completion_status");
786 return 1;
787 }
788
789 #[no_mangle]
790 pub extern "C" fn rs_dns_tx_get_alstate_progress(_tx: *mut std::os::raw::c_void,
791 _direction: u8)
792 -> std::os::raw::c_int
793 {
794 // This is a stateless parser, just the existence of a transaction
795 // means its complete.
796 SCLogDebug!("rs_dns_tx_get_alstate_progress");
797 return 1;
798 }
799
800 #[no_mangle]
801 pub extern "C" fn rs_dns_state_get_tx_count(state: *mut std::os::raw::c_void)
802 -> u64
803 {
804 let state = cast_pointer!(state, DNSState);
805 SCLogDebug!("rs_dns_state_get_tx_count: returning {}", state.tx_id);
806 return state.tx_id;
807 }
808
809 #[no_mangle]
810 pub extern "C" fn rs_dns_state_get_tx(state: *mut std::os::raw::c_void,
811 tx_id: u64)
812 -> *mut std::os::raw::c_void
813 {
814 let state = cast_pointer!(state, DNSState);
815 match state.get_tx(tx_id) {
816 Some(tx) => {
817 return unsafe{transmute(tx)};
818 }
819 None => {
820 return std::ptr::null_mut();
821 }
822 }
823 }
824
825 #[no_mangle]
826 pub extern "C" fn rs_dns_state_set_tx_detect_state(
827 tx: *mut std::os::raw::c_void,
828 de_state: &mut core::DetectEngineState) -> std::os::raw::c_int
829 {
830 let tx = cast_pointer!(tx, DNSTransaction);
831 tx.de_state = Some(de_state);
832 return 0;
833 }
834
835 #[no_mangle]
836 pub extern "C" fn rs_dns_state_get_tx_detect_state(
837 tx: *mut std::os::raw::c_void)
838 -> *mut core::DetectEngineState
839 {
840 let tx = cast_pointer!(tx, DNSTransaction);
841 match tx.de_state {
842 Some(ds) => {
843 return ds;
844 },
845 None => {
846 return std::ptr::null_mut();
847 }
848 }
849 }
850
851 #[no_mangle]
852 pub extern "C" fn rs_dns_state_get_events(tx: *mut std::os::raw::c_void)
853 -> *mut core::AppLayerDecoderEvents
854 {
855 let tx = cast_pointer!(tx, DNSTransaction);
856 return tx.events;
857 }
858
859 #[no_mangle]
860 pub extern "C" fn rs_dns_state_get_tx_data(
861 tx: *mut std::os::raw::c_void)
862 -> *mut AppLayerTxData
863 {
864 let tx = cast_pointer!(tx, DNSTransaction);
865 return &mut tx.tx_data;
866 }
867
868 #[no_mangle]
869 pub extern "C" fn rs_dns_tx_get_query_name(tx: &mut DNSTransaction,
870 i: u16,
871 buf: *mut *const u8,
872 len: *mut u32)
873 -> u8
874 {
875 if let &Some(ref request) = &tx.request {
876 if (i as usize) < request.queries.len() {
877 let query = &request.queries[i as usize];
878 if query.name.len() > 0 {
879 unsafe {
880 *len = query.name.len() as u32;
881 *buf = query.name.as_ptr();
882 }
883 return 1;
884 }
885 }
886 }
887 return 0;
888 }
889
890 /// Get the DNS transaction ID of a transaction.
891 //
892 /// extern uint16_t rs_dns_tx_get_tx_id(RSDNSTransaction *);
893 #[no_mangle]
894 pub extern "C" fn rs_dns_tx_get_tx_id(tx: &mut DNSTransaction) -> u16
895 {
896 return tx.tx_id()
897 }
898
899 /// Get the DNS response flags for a transaction.
900 ///
901 /// extern uint16_t rs_dns_tx_get_response_flags(RSDNSTransaction *);
902 #[no_mangle]
903 pub extern "C" fn rs_dns_tx_get_response_flags(tx: &mut DNSTransaction)
904 -> u16
905 {
906 return tx.rcode();
907 }
908
909 #[no_mangle]
910 pub extern "C" fn rs_dns_tx_get_query_rrtype(tx: &mut DNSTransaction,
911 i: u16,
912 rrtype: *mut u16)
913 -> u8
914 {
915 if let &Some(ref request) = &tx.request {
916 if (i as usize) < request.queries.len() {
917 let query = &request.queries[i as usize];
918 if query.name.len() > 0 {
919 unsafe {
920 *rrtype = query.rrtype;
921 }
922 return 1;
923 }
924 }
925 }
926 return 0;
927 }
928
929 #[no_mangle]
930 pub extern "C" fn rs_dns_probe(
931 _flow: *const core::Flow,
932 _dir: u8,
933 input: *const u8,
934 len: u32,
935 rdir: *mut u8,
936 ) -> AppProto {
937 if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 {
938 return core::ALPROTO_UNKNOWN;
939 }
940 let slice: &[u8] = unsafe {
941 std::slice::from_raw_parts(input as *mut u8, len as usize)
942 };
943 let (is_dns, is_request) = probe(slice);
944 if is_dns {
945 let dir = if is_request {
946 core::STREAM_TOSERVER
947 } else {
948 core::STREAM_TOCLIENT
949 };
950 unsafe {
951 *rdir = dir;
952 return ALPROTO_DNS;
953 }
954 }
955 return 0;
956 }
957
958 #[no_mangle]
959 pub extern "C" fn rs_dns_probe_tcp(
960 _flow: *const core::Flow,
961 direction: u8,
962 input: *const u8,
963 len: u32,
964 rdir: *mut u8
965 ) -> AppProto {
966 if len == 0 || len < std::mem::size_of::<DNSHeader>() as u32 + 2 {
967 return core::ALPROTO_UNKNOWN;
968 }
969 let slice: &[u8] = unsafe {
970 std::slice::from_raw_parts(input as *mut u8, len as usize)
971 };
972 //is_incomplete is checked by caller
973 let (is_dns, is_request, _) = probe_tcp(slice);
974 if is_dns {
975 let dir = if is_request {
976 core::STREAM_TOSERVER
977 } else {
978 core::STREAM_TOCLIENT
979 };
980 if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
981 unsafe { *rdir = dir };
982 }
983 return unsafe { ALPROTO_DNS };
984 }
985 return 0;
986 }
987
988 #[no_mangle]
989 pub extern "C" fn rs_dns_apply_tx_config(
990 _state: *mut std::os::raw::c_void, _tx: *mut std::os::raw::c_void,
991 _mode: std::os::raw::c_int, config: AppLayerTxConfig
992 ) {
993 let tx = cast_pointer!(_tx, DNSTransaction);
994 let state = cast_pointer!(_state, DNSState);
995 if let Some(request) = &tx.request {
996 if state.config.is_none() {
997 state.config = Some(ConfigTracker::new());
998 }
999 if let Some(ref mut tracker) = &mut state.config {
1000 tracker.add(request.header.tx_id, config);
1001 }
1002 }
1003 }
1004
1005 #[no_mangle]
1006 pub unsafe extern "C" fn rs_dns_init(proto: AppProto) {
1007 ALPROTO_DNS = proto;
1008 }
1009
1010 #[no_mangle]
1011 pub unsafe extern "C" fn rs_dns_udp_register_parser() {
1012 let default_port = std::ffi::CString::new("[53]").unwrap();
1013 let parser = RustParser{
1014 name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1015 default_port: default_port.as_ptr(),
1016 ipproto: IPPROTO_UDP,
1017 probe_ts: Some(rs_dns_probe),
1018 probe_tc: Some(rs_dns_probe),
1019 min_depth: 0,
1020 max_depth: std::mem::size_of::<DNSHeader>() as u16,
1021 state_new: rs_dns_state_new,
1022 state_free: rs_dns_state_free,
1023 tx_free: rs_dns_state_tx_free,
1024 parse_ts: rs_dns_parse_request,
1025 parse_tc: rs_dns_parse_response,
1026 get_tx_count: rs_dns_state_get_tx_count,
1027 get_tx: rs_dns_state_get_tx,
1028 tx_get_comp_st: rs_dns_state_progress_completion_status,
1029 tx_get_progress: rs_dns_tx_get_alstate_progress,
1030 get_events: Some(rs_dns_state_get_events),
1031 get_eventinfo: Some(rs_dns_state_get_event_info),
1032 get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id),
1033 localstorage_new: None,
1034 localstorage_free: None,
1035 get_files: None,
1036 get_tx_iterator: None,
1037 get_de_state: rs_dns_state_get_tx_detect_state,
1038 set_de_state: rs_dns_state_set_tx_detect_state,
1039 get_tx_data: rs_dns_state_get_tx_data,
1040 apply_tx_config: Some(rs_dns_apply_tx_config),
1041 flags: 0,
1042 };
1043
1044 let ip_proto_str = CString::new("udp").unwrap();
1045 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1046 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1047 ALPROTO_DNS = alproto;
1048 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1049 let _ = AppLayerRegisterParser(&parser, alproto);
1050 }
1051 AppLayerParserRegisterOptionFlags(IPPROTO_UDP as u8, ALPROTO_DNS,
1052 crate::applayer::APP_LAYER_PARSER_OPT_UNIDIR_TXS);
1053 }
1054 }
1055
1056 #[no_mangle]
1057 pub unsafe extern "C" fn rs_dns_tcp_register_parser() {
1058 let default_port = std::ffi::CString::new("53").unwrap();
1059 let parser = RustParser{
1060 name: b"dns\0".as_ptr() as *const std::os::raw::c_char,
1061 default_port: default_port.as_ptr(),
1062 ipproto: IPPROTO_TCP,
1063 probe_ts: Some(rs_dns_probe_tcp),
1064 probe_tc: Some(rs_dns_probe_tcp),
1065 min_depth: 0,
1066 max_depth: std::mem::size_of::<DNSHeader>() as u16 + 2,
1067 state_new: rs_dns_state_new,
1068 state_free: rs_dns_state_free,
1069 tx_free: rs_dns_state_tx_free,
1070 parse_ts: rs_dns_parse_request_tcp,
1071 parse_tc: rs_dns_parse_response_tcp,
1072 get_tx_count: rs_dns_state_get_tx_count,
1073 get_tx: rs_dns_state_get_tx,
1074 tx_get_comp_st: rs_dns_state_progress_completion_status,
1075 tx_get_progress: rs_dns_tx_get_alstate_progress,
1076 get_events: Some(rs_dns_state_get_events),
1077 get_eventinfo: Some(rs_dns_state_get_event_info),
1078 get_eventinfo_byid: Some(rs_dns_state_get_event_info_by_id),
1079 localstorage_new: None,
1080 localstorage_free: None,
1081 get_files: None,
1082 get_tx_iterator: None,
1083 get_de_state: rs_dns_state_get_tx_detect_state,
1084 set_de_state: rs_dns_state_set_tx_detect_state,
1085 get_tx_data: rs_dns_state_get_tx_data,
1086 apply_tx_config: Some(rs_dns_apply_tx_config),
1087 flags: 0,
1088 };
1089
1090 let ip_proto_str = CString::new("tcp").unwrap();
1091 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1092 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
1093 ALPROTO_DNS = alproto;
1094 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
1095 let _ = AppLayerRegisterParser(&parser, alproto);
1096 }
1097 AppLayerParserRegisterOptionFlags(IPPROTO_TCP as u8, ALPROTO_DNS,
1098 crate::applayer::APP_LAYER_PARSER_OPT_ACCEPT_GAPS);
1099 AppLayerParserRegisterOptionFlags(IPPROTO_TCP as u8, ALPROTO_DNS,
1100 crate::applayer::APP_LAYER_PARSER_OPT_UNIDIR_TXS);
1101 }
1102 }
1103
1104 #[cfg(test)]
1105 mod tests {
1106
1107 use super::*;
1108
1109 #[test]
1110 fn test_dns_parse_request_tcp_valid() {
1111 // A UDP DNS request with the DNS payload starting at byte 42.
1112 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1113 let buf: &[u8] = &[
1114 0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1115 0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1116 0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1117 0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1118 0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1119 0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1120 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1121 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1122 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1123 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1124 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1125 0x00, 0x00, 0x00 /* ... */
1126 ];
1127
1128 // The DNS payload starts at offset 42.
1129 let dns_payload = &buf[42..];
1130
1131 // Make a TCP DNS request payload.
1132 let mut request = Vec::new();
1133 request.push(((dns_payload.len() as u16) >> 8) as u8);
1134 request.push(((dns_payload.len() as u16) & 0xff) as u8);
1135 request.extend(dns_payload);
1136
1137 let mut state = DNSState::new();
1138 assert_eq!(1, state.parse_request_tcp(&request));
1139 }
1140
1141 #[test]
1142 fn test_dns_parse_request_tcp_short_payload() {
1143 // A UDP DNS request with the DNS payload starting at byte 42.
1144 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1145 let buf: &[u8] = &[
1146 0x00, 0x15, 0x17, 0x0d, 0x06, 0xf7, 0xd8, 0xcb, /* ........ */
1147 0x8a, 0xed, 0xa1, 0x46, 0x08, 0x00, 0x45, 0x00, /* ...F..E. */
1148 0x00, 0x4d, 0x23, 0x11, 0x00, 0x00, 0x40, 0x11, /* .M#...@. */
1149 0x41, 0x64, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10, /* Ad...... */
1150 0x01, 0x01, 0xa3, 0x4d, 0x00, 0x35, 0x00, 0x39, /* ...M.5.9 */
1151 0xb2, 0xb3, 0x8d, 0x32, 0x01, 0x20, 0x00, 0x01, /* ...2. .. */
1152 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x77, /* .......w */
1153 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1154 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1155 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1156 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00, /* ..)..... */
1157 0x00, 0x00, 0x00 /* ... */
1158 ];
1159
1160 // The DNS payload starts at offset 42.
1161 let dns_payload = &buf[42..];
1162
1163 // Make a TCP DNS request payload but with the length 1 larger
1164 // than the available data.
1165 let mut request = Vec::new();
1166 request.push(((dns_payload.len() as u16) >> 8) as u8);
1167 request.push(((dns_payload.len() as u16) & 0xff) as u8 + 1);
1168 request.extend(dns_payload);
1169
1170 let mut state = DNSState::new();
1171 assert_eq!(0, state.parse_request_tcp(&request));
1172 }
1173
1174 #[test]
1175 fn test_dns_parse_response_tcp_valid() {
1176 // A UDP DNS response with the DNS payload starting at byte 42.
1177 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1178 let buf: &[u8] = &[
1179 0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1180 0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1181 0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1182 0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1183 0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1184 0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1185 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1186 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1187 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1188 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1189 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1190 0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1191 0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1192 0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1193 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1194 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1195 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1196 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19 /* ....N. */
1197 ];
1198
1199 // The DNS payload starts at offset 42.
1200 let dns_payload = &buf[42..];
1201
1202 // Make a TCP DNS response payload.
1203 let mut request = Vec::new();
1204 request.push(((dns_payload.len() as u16) >> 8) as u8);
1205 request.push(((dns_payload.len() as u16) & 0xff) as u8);
1206 request.extend(dns_payload);
1207
1208 let mut state = DNSState::new();
1209 assert_eq!(1, state.parse_response_tcp(&request));
1210 }
1211
1212 // Test that a TCP DNS payload won't be parsed if there is not
1213 // enough data.
1214 #[test]
1215 fn test_dns_parse_response_tcp_short_payload() {
1216 // A UDP DNS response with the DNS payload starting at byte 42.
1217 // From pcap: https://github.com/jasonish/suricata-verify/blob/7cc0e1bd0a5249b52e6e87d82d57c0b6aaf75fce/dns-udp-dig-a-www-suricata-ids-org/dig-a-www.suricata-ids.org.pcap
1218 let buf: &[u8] = &[
1219 0xd8, 0xcb, 0x8a, 0xed, 0xa1, 0x46, 0x00, 0x15, /* .....F.. */
1220 0x17, 0x0d, 0x06, 0xf7, 0x08, 0x00, 0x45, 0x00, /* ......E. */
1221 0x00, 0x80, 0x65, 0x4e, 0x40, 0x00, 0x40, 0x11, /* ..eN@.@. */
1222 0xbe, 0xf3, 0x0a, 0x10, 0x01, 0x01, 0x0a, 0x10, /* ........ */
1223 0x01, 0x0b, 0x00, 0x35, 0xa3, 0x4d, 0x00, 0x6c, /* ...5.M.l */
1224 0x8d, 0x8c, 0x8d, 0x32, 0x81, 0xa0, 0x00, 0x01, /* ...2.... */
1225 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, /* .......w */
1226 0x77, 0x77, 0x0c, 0x73, 0x75, 0x72, 0x69, 0x63, /* ww.suric */
1227 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, 0x73, 0x03, /* ata-ids. */
1228 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, /* org..... */
1229 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, /* ........ */
1230 0x0d, 0xd8, 0x00, 0x12, 0x0c, 0x73, 0x75, 0x72, /* .....sur */
1231 0x69, 0x63, 0x61, 0x74, 0x61, 0x2d, 0x69, 0x64, /* icata-id */
1232 0x73, 0x03, 0x6f, 0x72, 0x67, 0x00, 0xc0, 0x32, /* s.org..2 */
1233 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1234 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x18, 0xc0, 0x32, /* ....N..2 */
1235 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf4, /* ........ */
1236 0x00, 0x04, 0xc0, 0x00, 0x4e, 0x19 /* ....N. */
1237 ];
1238
1239 // The DNS payload starts at offset 42.
1240 let dns_payload = &buf[42..];
1241
1242 // Make a TCP DNS response payload, but make the length 1 byte
1243 // larger than the actual size.
1244 let mut request = Vec::new();
1245 request.push(((dns_payload.len() as u16) >> 8) as u8);
1246 request.push((((dns_payload.len() as u16) & 0xff) + 1) as u8);
1247 request.extend(dns_payload);
1248
1249 let mut state = DNSState::new();
1250 assert_eq!(0, state.parse_response_tcp(&request));
1251 }
1252
1253 // Port of the C RustDNSUDPParserTest02 unit test.
1254 #[test]
1255 fn test_dns_udp_parser_test_01() {
1256 /* query: abcdefghijk.com
1257 * TTL: 86400
1258 * serial 20130422 refresh 28800 retry 7200 exp 604800 min ttl 86400
1259 * ns, hostmaster */
1260 let buf: &[u8] = &[
1261 0x00, 0x3c, 0x85, 0x00, 0x00, 0x01, 0x00, 0x00,
1262 0x00, 0x01, 0x00, 0x00, 0x0b, 0x61, 0x62, 0x63,
1263 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
1264 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x0f, 0x00,
1265 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01,
1266 0x51, 0x80, 0x00, 0x25, 0x02, 0x6e, 0x73, 0x00,
1267 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73,
1268 0x74, 0x65, 0x72, 0xc0, 0x2f, 0x01, 0x33, 0x2a,
1269 0x76, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c,
1270 0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51,
1271 0x80,
1272 ];
1273 let mut state = DNSState::new();
1274 assert!(state.parse_response(buf));
1275 }
1276
1277 // Port of the C RustDNSUDPParserTest02 unit test.
1278 #[test]
1279 fn test_dns_udp_parser_test_02() {
1280 let buf: &[u8] = &[
1281 0x6D,0x08,0x84,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x03,0x57,0x57,0x57,
1282 0x04,0x54,0x54,0x54,0x54,0x03,0x56,0x56,0x56,0x03,0x63,0x6F,0x6D,0x02,0x79,0x79,
1283 0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,
1284 0x02,0xC0,0x0C,0xC0,0x31,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,
1285 0x31,0xC0,0x3F,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x3F,0xC0,
1286 0x4D,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x4D,0xC0,0x5B,0x00,
1287 0x05,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x5B,0xC0,0x69,0x00,0x05,0x00,
1288 0x01,0x00,0x00,0x0E,0x10,0x00,0x02,0xC0,0x69,0xC0,0x77,0x00,0x05,0x00,0x01,0x00,
1289 0x00,0x0E,0x10,0x00,0x02,0xC0,0x77,0xC0,0x85,0x00,0x05,0x00,0x01,0x00,0x00,0x0E,
1290 0x10,0x00,0x02,0xC0,0x85,0x00,0x00,0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1291 ];
1292 let mut state = DNSState::new();
1293 assert!(state.parse_response(buf));
1294 }
1295
1296 // Port of the C RustDNSUDPParserTest03 unit test.
1297 #[test]
1298 fn test_dns_udp_parser_test_03() {
1299 let buf: &[u8] = &[
1300 0x6F,0xB4,0x84,0x80,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x03,0x57,0x57,0x77,
1301 0x0B,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x03,0x55,0x55,0x55,
1302 0x02,0x79,0x79,0x00,0x00,0x01,0x00,0x01,0xC0,0x0C,0x00,0x05,0x00,0x01,0x00,0x00,
1303 0x0E,0x10,0x00,0x02,0xC0,0x10,0xC0,0x34,0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,
1304 0x00,0x04,0xC3,0xEA,0x04,0x19,0xC0,0x34,0x00,0x02,0x00,0x01,0x00,0x00,0x0E,0x10,
1305 0x00,0x0A,0x03,0x6E,0x73,0x31,0x03,0x61,0x67,0x62,0xC0,0x20,0xC0,0x46,0x00,0x02,
1306 0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x06,0x03,0x6E,0x73,0x32,0xC0,0x56,0xC0,0x52,
1307 0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x04,0x0A,0xC0,0x68,
1308 0x00,0x01,0x00,0x01,0x00,0x00,0x0E,0x10,0x00,0x04,0xC3,0xEA,0x05,0x14,0x00,0x00,
1309 0x29,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00
1310 ];
1311 let mut state = DNSState::new();
1312 assert!(state.parse_response(buf));
1313 }
1314
1315 // Port of the C RustDNSUDPParserTest04 unit test.
1316 //
1317 // Test the TXT records in an answer.
1318 #[test]
1319 fn test_dns_udp_parser_test_04() {
1320 let buf: &[u8] = &[
1321 0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1322 0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1323 0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1324 0x01,
1325 /* answer record start */
1326 0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1327 /* txt record starts: */
1328 0x20, /* <txt len 32 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1329 0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1330 0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
1331 0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1332 0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1333 ];
1334 let mut state = DNSState::new();
1335 assert!(state.parse_response(buf));
1336 }
1337
1338 // Port of the C RustDNSUDPParserTest05 unit test.
1339 //
1340 // Test TXT records in answer with a bad length.
1341 #[test]
1342 fn test_dns_udp_parser_test_05() {
1343 let buf: &[u8] = &[
1344 0xc2,0x2f,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x0a,0x41,0x41,0x41,
1345 0x41,0x41,0x4f,0x31,0x6b,0x51,0x41,0x05,0x3d,0x61,0x75,0x74,0x68,0x03,0x73,0x72,
1346 0x76,0x06,0x74,0x75,0x6e,0x6e,0x65,0x6c,0x03,0x63,0x6f,0x6d,0x00,0x00,0x10,0x00,
1347 0x01,
1348 /* answer record start */
1349 0xc0,0x0c,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x22,
1350 /* txt record starts: */
1351 0x40, /* <txt len 64 */ 0x41,0x68,0x76,0x4d,0x41,0x41,0x4f,0x31,0x6b,0x41,0x46,
1352 0x45,0x35,0x54,0x45,0x39,0x51,0x54,0x6a,0x46,0x46,0x4e,0x30,0x39,0x52,0x4e,0x31,
1353 0x6c,0x59,0x53,0x44,0x6b,0x00, /* <txt len 0 */ 0xc0,0x1d,0x00,0x02,0x00,0x01,
1354 0x00,0x09,0x3a,0x80,0x00,0x09,0x06,0x69,0x6f,0x64,0x69,0x6e,0x65,0xc0,0x21,0xc0,
1355 0x6b,0x00,0x01,0x00,0x01,0x00,0x09,0x3a,0x80,0x00,0x04,0x0a,0x1e,0x1c,0x5f
1356 ];
1357 let mut state = DNSState::new();
1358 assert!(!state.parse_response(buf));
1359 }
1360
1361 // Port of the C RustDNSTCPParserTestMultiRecord unit test.
1362 #[test]
1363 fn test_dns_tcp_parser_multi_record() {
1364 let buf: &[u8] = &[
1365 0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
1366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
1367 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1368 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1369 0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
1371 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1372 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1373 0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
1374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
1375 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1376 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1377 0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
1379 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1380 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1381 0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
1382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
1383 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1384 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1385 0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
1386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
1387 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1388 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1389 0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
1390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
1391 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1392 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1393 0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
1394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
1395 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1396 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1397 0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
1398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
1399 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1400 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1401 0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
1402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
1403 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1404 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1405 0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
1406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1407 0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1408 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1409 0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
1410 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1411 0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1412 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1413 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
1414 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1415 0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
1416 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
1417 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
1418 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1419 0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
1420 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
1421 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
1422 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1423 0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
1424 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
1425 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
1426 0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1427 0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
1428 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
1429 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
1430 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
1432 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
1433 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
1434 0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
1435 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
1436 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
1437 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
1438 0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
1439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
1440 0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
1441 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
1442 0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
1443 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
1444 0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
1445 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
1446 0x00, 0x01
1447 ];
1448 let mut state = DNSState::new();
1449 assert_eq!(state.parse_request_tcp(buf), 20);
1450 }
1451 }