]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dns: log rdata for NULL record type
authorSimon Dugas <simdugas@gmail.com>
Wed, 22 Apr 2020 17:29:32 +0000 (17:29 +0000)
committerVictor Julien <victor@inliniac.net>
Tue, 8 Dec 2020 16:15:47 +0000 (17:15 +0100)
Logs the rdata for a NULL record type as a printable string.

rust/src/dns/dns.rs
rust/src/dns/log.rs
rust/src/dns/lua.rs
rust/src/dns/parser.rs

index e876be23c8ea4f0c417bd8ed613197a42c8e25fa..41029685802ba80b2abd0adb37f3329c8fec6fe2 100644 (file)
@@ -271,6 +271,7 @@ pub enum DNSRData {
     MX(Vec<u8>),
     // RData is text
     TXT(Vec<u8>),
+    NULL(Vec<u8>),
     // RData has several fields
     SOA(DNSRDataSOA),
     SSHFP(DNSRDataSSHFP),
index c27076be45ec2f3667912efd3ddb56d7ad6dc212..02519b81351b05685ba1a8aa27d2e952d4d2d5f8 100644 (file)
@@ -444,6 +444,7 @@ fn dns_log_json_answer_detail(answer: &DNSAnswerEntry) -> Result<JsonBuilder, Js
         DNSRData::CNAME(bytes) |
         DNSRData::MX(bytes) |
         DNSRData::TXT(bytes) |
+        DNSRData::NULL(bytes) |
         DNSRData::PTR(bytes) => {
             jsa.set_string_from_bytes("rdata", &bytes)?;
         }
@@ -515,6 +516,7 @@ fn dns_log_json_answer(js: &mut JsonBuilder, response: &DNSResponse, flags: u64)
                     DNSRData::CNAME(bytes) |
                     DNSRData::MX(bytes) |
                     DNSRData::TXT(bytes) |
+                    DNSRData::NULL(bytes) |
                     DNSRData::PTR(bytes) => {
                         if !answer_types.contains_key(&type_string) {
                             answer_types.insert(type_string.to_string(),
@@ -687,6 +689,7 @@ fn dns_log_json_answer_v1(header: &DNSHeader, answer: &DNSAnswerEntry)
         DNSRData::CNAME(bytes) |
         DNSRData::MX(bytes) |
         DNSRData::TXT(bytes) |
+        DNSRData::NULL(bytes) |
         DNSRData::PTR(bytes) => {
             js.set_string_from_bytes("rdata", &bytes)?;
         }
index 6a7ea26921371d84662b1b7c8488548af674b1c2..570c71e5123f0b5e59e767738f240017fd8b2841 100644 (file)
@@ -177,6 +177,7 @@ pub extern "C" fn rs_dns_lua_get_answer_table(clua: &mut CLuaState,
                 DNSRData::CNAME(ref bytes) |
                 DNSRData::MX(ref bytes) |
                 DNSRData::TXT(ref bytes) |
+                DNSRData::NULL(ref bytes) |
                 DNSRData::PTR(ref bytes) |
                 DNSRData::Unknown(ref bytes) => {
                     if bytes.len() > 0 {
index 0f7038dda61475ed7c31d65d9a97c5ad63856acc..a59a09fbaad096e0b09a48d15ea3a84e95a53dbe 100644 (file)
@@ -323,6 +323,15 @@ fn dns_parse_rdata_txt<'a>(input: &'a [u8])
     )
 }
 
+fn dns_parse_rdata_null<'a>(input: &'a [u8])
+                            -> IResult<&'a [u8], DNSRData> {
+    do_parse!(
+        input,
+        data: take!(input.len()) >>
+            (DNSRData::NULL(data.to_vec()))
+    )
+}
+
 fn dns_parse_rdata_sshfp<'a>(input: &'a [u8])
                              -> IResult<&'a [u8], DNSRData> {
     do_parse!(
@@ -354,6 +363,7 @@ pub fn dns_parse_rdata<'a>(input: &'a [u8], message: &'a [u8], rrtype: u16)
         DNS_RECORD_TYPE_SOA => dns_parse_rdata_soa(input, message),
         DNS_RECORD_TYPE_MX => dns_parse_rdata_mx(input, message),
         DNS_RECORD_TYPE_TXT => dns_parse_rdata_txt(input),
+        DNS_RECORD_TYPE_NULL => dns_parse_rdata_null(input),
         DNS_RECORD_TYPE_SSHFP => dns_parse_rdata_sshfp(input),
         _ => dns_parse_rdata_unknown(input),
     }
@@ -669,6 +679,65 @@ mod tests {
         }
     }
 
+
+    #[test]
+    fn test_dns_parse_response_null() {
+        // DNS response with a NULL record from
+        // https://redmine.openinfosecfoundation.org/attachments/2062
+
+        let pkt: &[u8] = &[
+            0x12, 0xb0, 0x84, 0x00, 0x00, 0x01, 0x00, 0x01, /* ........ */
+            0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x61, 0x61, /* .....vaa */
+            0x61, 0x61, 0x6b, 0x61, 0x72, 0x64, 0x6c, 0x69, /* aakardli */
+            0x06, 0x70, 0x69, 0x72, 0x61, 0x74, 0x65, 0x03, /* .pirate. */
+            0x73, 0x65, 0x61, 0x00, 0x00, 0x0a, 0x00, 0x01, /* sea..... */
+            0xc0, 0x0c, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, /* ........ */
+            0x00, 0x00, 0x00, 0x09, 0x56, 0x41, 0x43, 0x4b, /* ....VACK */
+            0x44, 0x03, 0xc5, 0xe9, 0x01,                   /* D.... */
+        ];
+
+        let res = dns_parse_response(pkt);
+        match res {
+            Ok((rem, response)) => {
+                // The response should be fully parsed.
+                assert_eq!(rem.len(), 0);
+
+                assert_eq!(response.header, DNSHeader {
+                    tx_id: 0x12b0,
+                    flags: 0x8400,
+                    questions: 1,
+                    answer_rr: 1,
+                    authority_rr: 0,
+                    additional_rr: 0,
+                });
+
+                assert_eq!(response.queries.len(), 1);
+                let query = &response.queries[0];
+                assert_eq!(query.name,
+                           "vaaaakardli.pirate.sea".as_bytes().to_vec());
+                assert_eq!(query.rrtype, DNS_RECORD_TYPE_NULL);
+                assert_eq!(query.rrclass, 1);
+
+                assert_eq!(response.answers.len(), 1);
+
+                let answer = &response.answers[0];
+                assert_eq!(answer.name,
+                           "vaaaakardli.pirate.sea".as_bytes().to_vec());
+                assert_eq!(answer.rrtype, DNS_RECORD_TYPE_NULL);
+                assert_eq!(answer.rrclass, 1);
+                assert_eq!(answer.ttl, 0);
+                assert_eq!(answer.data, DNSRData::NULL(vec![
+                        0x56, 0x41, 0x43, 0x4b,       /* VACK */
+                        0x44, 0x03, 0xc5, 0xe9, 0x01, /* D.... */
+                        ]));
+            },
+            _ => {
+                assert!(false);
+            }
+        }
+    }
+
+
     #[test]
     fn test_dns_parse_rdata_sshfp() {
         // Dummy data since we don't have a pcap sample.