]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb: add unit tests
authorLancer Cheng <b1tg@protonmail.ch>
Tue, 4 Apr 2023 15:29:10 +0000 (15:29 +0000)
committerVictor Julien <vjulien@oisf.net>
Fri, 5 May 2023 09:37:34 +0000 (11:37 +0200)
Issue: 4865

rust/src/smb/smb2_records.rs
rust/src/smb/smb3.rs

index b19379883a77799adb4c8482d5ade2a9448b98ea..2eb0050618387af56cc953189226333117730c1d 100644 (file)
@@ -345,7 +345,7 @@ pub fn parse_smb2_request_close(i: &[u8]) -> IResult<&[u8], Smb2CloseRequestReco
     Ok((i, record))
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 pub struct Smb2SetInfoRequestRenameRecord<'a> {
     pub name: &'a[u8],
 }
@@ -360,7 +360,7 @@ pub fn parse_smb2_request_setinfo_rename(i: &[u8]) -> IResult<&[u8], Smb2SetInfo
     Ok((i, record))
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 pub struct Smb2SetInfoRequestDispoRecord {
     pub delete: bool,
 }
@@ -373,7 +373,7 @@ pub fn parse_smb2_request_setinfo_disposition(i: &[u8]) -> IResult<&[u8], Smb2Se
     Ok((i, record))
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 pub enum Smb2SetInfoRequestData<'a> {
     DISPOSITION(Smb2SetInfoRequestDispoRecord),
     RENAME(Smb2SetInfoRequestRenameRecord<'a>),
@@ -626,3 +626,240 @@ pub fn search_smb_record(i: &[u8]) -> IResult<&[u8], &[u8]> {
     }
     Err(Err::Incomplete(Needed::new(4_usize - d.len())))
 }
+
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+       use crate::smb::smb2::smb2_dialect_string;
+       use std::convert::TryInto;
+    fn guid_to_string(guid: &[u8]) -> String {
+        if guid.len() == 16 {
+            let output = format!("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
+                    guid[3],  guid[2],  guid[1],  guid[0],
+                    guid[5],  guid[4],  guid[7],  guid[6],
+                    guid[9],  guid[8],  guid[11], guid[10],
+                    guid[15], guid[14], guid[13], guid[12]);
+            output
+        } else {
+            "".to_string()
+        }
+    }
+    #[test]
+    fn test_parse_smb2_request_record() {
+        let data = hex::decode("fe534d42400000000000000000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+        let result = parse_smb2_request_record(&data).unwrap();
+        let record: Smb2Record = result.1;
+        assert_eq!(record, Smb2Record {
+            direction: 1,
+            header_len: 64,
+            nt_status: 0,
+            command: 0,
+            message_id: 0,
+            tree_id: 0,
+            async_id: 0,
+            session_id: 0,
+            data: &[],
+        });
+    }
+    #[test]
+    fn test_parse_smb2_request_negotiate_protocol() {
+        // https://github.com/bro/bro/blob/master/testing/btest/Traces/smb/smb3_negotiate_context.pcap
+        // smb3_negotiate_context.pcap no.12
+        let data = hex::decode("24000800010000007f00000016ab4fd9625676488cd1707d08e52b5878000000020000000202100222022402000302031003110300000000010026000000000001002000010067e5f669ff3e0ad12e89ad84ceb1d35dfee53ede3e4858a6d1a9099ac1635a9600000200060000000000020001000200").unwrap();
+        let result = parse_smb2_request_negotiate_protocol(&data).unwrap();
+        let record: Smb2NegotiateProtocolRequestRecord = result.1;
+        let dialects:Vec<String> = record.dialects_vec.iter().map(|d|smb2_dialect_string(*d)).collect();
+        assert_eq!(dialects, ["2.02", "2.10", "2.22", "2.24", "3.00", "3.02", "3.10", "3.11"]);
+        assert_eq!(guid_to_string(record.client_guid), "d94fab16-5662-4876-d18c-7d70582be508"); // TODO: guid order
+    }
+
+    #[test]
+    fn test_parse_smb2_response_tree_connect() {
+        // https://github.com/bro/bro/blob/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:smb2 no.11
+        let data = hex::decode("100001000008000000000000ff011f00").unwrap();
+        let result = parse_smb2_response_tree_connect(&data).unwrap();
+        let record: Smb2TreeConnectResponseRecord = result.1;
+        assert_eq!(record.share_type, 1); // 1: SMB2_SHARE_TYPE_DISK
+    }
+    #[test]
+    fn test_parse_smb2_request_create() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:smb2 no.26
+        let data = hex::decode("390000000200000000000000000000000000000000000000810010008000000003000000020000002100200078000000800000005800000000007200760073002800000010000400000018001000000044486e510000000000000000000000000000000000000000180000001000040000001800000000004d78416300000000000000001000040000001800000000005146696400000000").unwrap();
+        let result = parse_smb2_request_create(&data).unwrap();
+        let record: Smb2CreateRequestRecord = result.1;
+        assert_eq!(record.disposition, 2); // FILE_CREATE: 2
+        assert_eq!(record.create_options, 0x200021);
+        assert_eq!(record.data, &[]);
+        let del = record.create_options & 0x0000_1000 != 0;
+        let dir = record.create_options & 0x0000_0001 != 0;
+        assert_eq!(del, false);
+        assert_eq!(dir, true);
+    }
+    #[test]
+    fn test_parse_smb2_request_close() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:smb2 no.24
+        let data = hex::decode("1800000000000000490000000000000005000000ffffffff").unwrap();
+        let result = parse_smb2_request_close(&data).unwrap();
+        let record: Smb2CloseRequestRecord = result.1;
+        assert_eq!(guid_to_string(record.guid), "00000049-0000-0000-0005-0000ffffffff");
+    }
+
+    #[test]
+    fn test_parse_smb2_request_setinfo() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:tcp.stream eq 0 no.36
+        let data = hex::decode("210001140800000060000000000000004d0000000000000009000000ffffffff4b06170000000000").unwrap();
+        let result = parse_smb2_request_setinfo(&data).unwrap();
+        let record: Smb2SetInfoRequestRecord = result.1;
+        assert_eq!(record.class, 1);
+        assert_eq!(record.infolvl, 20);
+        assert_eq!(record.data, Smb2SetInfoRequestData::UNHANDLED);
+        assert_eq!(guid_to_string(record.guid), "0000004d-0000-0000-0009-0000ffffffff");
+    }
+
+    #[test]
+    fn test_parse_smb2_request_read() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:smb2 no.20
+        let data = hex::decode("31005000000400000000000000000000490000000000000005000000ffffffff00000000000000000000000000000000").unwrap();
+        let result = parse_smb2_request_read(&data).unwrap();
+        let record: Smb2ReadRequestRecord = result.1;
+        assert_eq!(record.rd_len, 1024);
+        assert_eq!(record.rd_offset, 0);
+        assert_eq!(guid_to_string(record.guid), "00000049-0000-0000-0005-0000ffffffff");
+    }
+
+    #[test]
+    fn test_parse_smb2_request_write() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:tcp.stream eq 0 no.18
+        let data = hex::decode("31007000740000000000000000000000490000000000000005000000ffffffff0000000000000000000000000000000005000b03100000007400000001000000b810b810000000000200000000000100c84f324b7016d30112785a47bf6ee18803000000045d888aeb1cc9119fe808002b1048600200000001000100c84f324b7016d30112785a47bf6ee188030000002c1cb76c12984045030000000000000001000000").unwrap();
+        let result = parse_smb2_request_write(&data).unwrap();
+        let record: Smb2WriteRequestRecord = result.1;
+        assert_eq!(record.wr_len, 116);
+        assert_eq!(record.wr_offset, 0);
+        assert_eq!(guid_to_string(record.guid), "00000049-0000-0000-0005-0000ffffffff");
+        assert_eq!(record.data.len(), 116);
+    }
+
+
+    #[test]
+    fn test_parse_smb2_response_read() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
+        // filter:tcp.stream eq 0 no.21
+        let data = hex::decode("110050005c000000000000000000000005000c03100000005c00000001000000b810b810b97200000d005c504950455c73727673766300000200000000000000045d888aeb1cc9119fe808002b10486002000000030003000000000000000000000000000000000000000000").unwrap();
+        let result = parse_smb2_response_read(&data).unwrap();
+        let record: Smb2ReadResponseRecord = result.1;
+        assert_eq!(record.len, 92);
+        assert_eq!(record.data.len(), 92);
+
+    }
+    #[test]
+    fn test_parse_smb2_record_direction() {
+        let data = hex::decode("fe534d42400000000000000000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+        let result = parse_smb2_record_direction(&data).unwrap();
+        let record: Smb2RecordDir = result.1;
+        assert_eq!(record.request, false);
+        let data = hex::decode("fe534d4240000000000000000100080000000000000000000100000000000000fffe000000000000000000000000000000000000000000000000000000000000").unwrap();
+        let result = parse_smb2_record_direction(&data).unwrap();
+        let record: Smb2RecordDir = result.1;
+        assert_eq!(record.request, true);
+    }
+
+       #[test]
+       fn test_parse_smb2_request_tree_connect() {
+               let data = hex::decode("0900000048002c005c005c003100390032002e003100360038002e003100390039002e003100330033005c004900500043002400").unwrap();
+               let result = parse_smb2_request_tree_connect(&data);
+        assert_eq!(result.is_ok(), true);
+        let record = result.unwrap().1;
+        assert!(record.share_name.len() > 2);
+               let share_name_len = u16::from_le_bytes(record.share_name[0..2].try_into().unwrap());
+               assert_eq!(share_name_len ,44);
+               assert_eq!(record.share_name.len() ,share_name_len as usize + 2);
+               let mut share_name = record.share_name[2..].to_vec();
+               share_name.retain(|&i|i != 0x00);
+               assert_eq!(String::from_utf8_lossy(&share_name), "\\\\192.168.199.133\\IPC$");
+       }
+
+       #[test]
+       fn test_parse_smb2_response_record() {
+        let data = hex::decode("fe534d4240000000000000000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041000100ff020000966eafa3357f0440a5f9643e1bfa8c56070000000000800000008000000080001064882d8527d201a1f3ae878427d20180004001000000006082013c06062b0601050502a08201303082012ca01a3018060a2b06010401823702021e060a2b06010401823702020aa282010c048201084e45474f45585453010000000000000060000000700000007fb23ba7cacc4e216323ca8472061efbd2c4f6d6b3017012f0bf4f7202ec684ee801ef64e55401ab86b1c9ebde4e39ea0000000000000000600000000100000000000000000000005c33530deaf90d4db2ec4ae3786ec3084e45474f45585453030000000100000040000000980000007fb23ba7cacc4e216323ca8472061efb5c33530deaf90d4db2ec4ae3786ec30840000000580000003056a05430523027802530233121301f06035504031318546f6b656e205369676e696e67205075626c6963204b65793027802530233121301f06035504031318546f6b656e205369676e696e67205075626c6963204b6579").unwrap();
+        let result = parse_smb2_response_record(&data);
+        assert_eq!(result.is_ok(), true);
+        let record = result.unwrap().1;
+        assert_eq!(record.direction, 1);
+               assert_eq!(record.header_len, 64);
+               assert_eq!(record.nt_status, 0);
+               assert_eq!(record.command, crate::smb::smb2::SMB2_COMMAND_NEGOTIATE_PROTOCOL);
+               assert_eq!(record.message_id, 0);
+               assert_eq!(record.tree_id, 0);
+               assert_eq!(record.async_id, 0);
+               assert_eq!(record.session_id, 0);
+               let neg_proto_result = parse_smb2_response_negotiate_protocol(record.data);
+        assert_eq!(neg_proto_result.is_ok(), true);
+        let neg_proto = neg_proto_result.unwrap().1;
+               assert_eq!(guid_to_string(neg_proto.server_guid), "a3af6e96-7f35-4004-f9a5-3e64568cfa1b");
+               assert_eq!(neg_proto.dialect, 0x2ff);
+               assert_eq!(smb2_dialect_string(neg_proto.dialect), "2.??".to_string());
+               assert_eq!(neg_proto.max_trans_size, 0x800000);
+               assert_eq!(neg_proto.max_read_size, 0x800000);
+               assert_eq!(neg_proto.max_write_size, 0x800000);
+    }
+
+    #[test]
+    fn test_todo_parse_smb2_response_negotiate_protocol_error() {
+        // TODO: find pcap
+    }
+
+       #[test]
+       fn test_parse_smb2_response_write() {
+        let data = hex::decode("11000000a00000000000000000000000").unwrap();
+        let result = parse_smb2_response_write(&data);
+        assert_eq!(result.is_ok(), true);
+        let record = result.unwrap().1;
+               assert_eq!(record.wr_cnt, 160);
+       }
+       #[test]
+       fn test_parse_smb2_response_create() {
+        let data = hex::decode("5900000001000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000800000000000000001000000db3b5a009a29ea00000000000000000000000000").unwrap();
+        let result = parse_smb2_response_create(&data);
+        assert_eq!(result.is_ok(), true);
+        let record = result.unwrap().1;
+               assert_eq!(guid_to_string(record.guid), "00000001-3bdb-005a-299a-00ea00000000");
+               assert_eq!(record.create_ts, SMBFiletime::new(0));
+               assert_eq!(record.last_access_ts, SMBFiletime::new(0));
+               assert_eq!(record.last_write_ts, SMBFiletime::new(0));
+               assert_eq!(record.last_change_ts, SMBFiletime::new(0));
+               assert_eq!(record.size, 0);
+
+       }
+       #[test]
+       fn test_parse_smb2_response_ioctl() {
+        let data = hex::decode("31000000fc011400ffffffffffffffffffffffffffffffff7000000000000000700000003001000000000000000000009800000004000000010000000000000000ca9a3b0000000002000000c0a8c7850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000010000000000000000ca9a3b000000001700000000000000fe8000000000000065b53a9792d191990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+        let result = parse_smb2_response_ioctl(&data);
+        assert_eq!(result.is_ok(), true);
+        let record = result.unwrap().1;
+               assert_eq!(record.indata_len, 0);
+               assert_eq!(guid_to_string(record.guid), "ffffffff-ffff-ffff-ffff-ffffffffffff");
+               assert_eq!(record.is_pipe, false);
+               assert_eq!(record.outdata_len, 304);
+               assert_eq!(record.indata_offset, 112);
+               assert_eq!(record.outdata_offset, 112);
+       }
+
+       #[test]
+       fn test_parse_smb2_request_ioctl() {
+        let data = hex::decode("39000000fc011400ffffffffffffffffffffffffffffffff7800000000000000000000007800000000000000000001000100000000000000").unwrap();
+        let result = parse_smb2_request_ioctl(&data);
+        assert_eq!(result.is_ok(), true);
+        let record = result.unwrap().1;
+               assert_eq!(guid_to_string(record.guid), "ffffffff-ffff-ffff-ffff-ffffffffffff");
+               assert_eq!(record.is_pipe, false);
+               assert_eq!(record.function, 0x1401fc);
+               assert_eq!(record.data, &[]);
+       }
+}
index 287a5cf4b3eeaa4e7e6a5be01c6f5728b89ca7e9..07a7059955029b536268b64b50300cbe6b75365c 100644 (file)
@@ -42,3 +42,18 @@ pub fn parse_smb3_transform_record(i: &[u8]) -> IResult<&[u8], Smb3TransformReco
     };
     Ok((i, record))
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+       #[test]
+       fn test_parse_smb3_transform_record() {
+        // https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb3.pcap
+        let data = hex::decode("fd534d42188d39cea4b1e3f640aff5d0b1569852c0bd665516dbb4b499507f000000000069000000000001003d00009400480000d9f8a66572b40c621bea6f5922a412a8eb2e3cc2af9ce26a277e75898cb523b9eb49ef660a6a1a09368fadd6a58e893e08eb3b7c068bdb74b6cd38e9ed1a2559cefb2ebc2172fd86c08a1a636eb851f20bf53a242f4cfaf7ab44e77291073ad492d6297c3d3a67757c").unwrap();
+        let result = parse_smb3_transform_record(&data).unwrap();
+        let record: Smb3TransformRecord = result.1;
+        assert_eq!(record.session_id, 79167320227901);
+        assert_eq!(record.enc_algo, 1);
+        assert_eq!(record.enc_data.len(), 105);
+    }
+}