smb_msg/
smb1.rs

1//! SMBv1 negotiation packet support.
2//!
3//! For multi-protocol negotiation only.
4
5use binrw::io::TakeSeekExt;
6use binrw::prelude::*;
7
8use smb_dtyp::binrw_util::prelude::*;
9
10#[binrw::binrw]
11#[derive(Debug)]
12#[brw(little)]
13#[brw(magic(b"\xffSMB"))]
14pub struct SMB1NegotiateMessage {
15    #[bw(calc = 0x72)]
16    #[br(assert(_command == 0x72))]
17    _command: u8,
18    status: u32,
19    flags: u8,
20    flags2: u16,
21    #[bw(calc = 0)]
22    #[br(assert(_pid_high == 0))]
23    _pid_high: u16,
24    security_features: [u8; 8],
25    #[bw(calc = 0)]
26    _reserved: u16,
27    #[bw(calc = 0xffff)]
28    _tid: u16,
29    #[bw(calc = 1)]
30    #[br(assert(_pid_low == 1))]
31    _pid_low: u16,
32    #[bw(calc = 0)]
33    _uid: u16,
34    #[bw(calc = 0)]
35    _mid: u16,
36    // word count is always 0x0 according to MS-CIFS.
37    #[bw(calc = 0)]
38    #[br(assert(_word_count == 0))]
39    _word_count: u8,
40    byte_count: PosMarker<u16>,
41    #[br(map_stream = |s| s.take_seek(byte_count.value.into()), parse_with = binrw::helpers::until_eof)]
42    #[bw(write_with = PosMarker::write_size, args(byte_count))]
43    dialects: Vec<Smb1Dialect>,
44}
45
46impl SMB1NegotiateMessage {
47    pub fn is_smb2_supported(&self) -> bool {
48        self.dialects
49            .iter()
50            .any(|d| d.name.to_string() == "SMB 2.002")
51    }
52}
53
54impl Default for SMB1NegotiateMessage {
55    fn default() -> Self {
56        Self {
57            status: 0,
58            flags: 0x18,
59            flags2: 0xc853,
60            security_features: [0; 8],
61            byte_count: PosMarker::default(),
62            dialects: vec![
63                Smb1Dialect {
64                    name: binrw::NullString::from("NT LM 0.12"),
65                },
66                Smb1Dialect {
67                    name: binrw::NullString::from("SMB 2.002"),
68                },
69                Smb1Dialect {
70                    name: binrw::NullString::from("SMB 2.???"),
71                },
72            ],
73        }
74    }
75}
76
77#[derive(BinRead, BinWrite, Debug)]
78#[brw(magic(b"\x02"))]
79pub struct Smb1Dialect {
80    name: binrw::NullString,
81}
82
83impl TryInto<Vec<u8>> for SMB1NegotiateMessage {
84    type Error = binrw::Error;
85    fn try_into(self) -> Result<Vec<u8>, Self::Error> {
86        let mut buf = std::io::Cursor::new(Vec::new());
87        self.write(&mut buf)?;
88        Ok(buf.into_inner())
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    smb_tests::test_binrw_write! {
97        SMB1NegotiateMessage: SMB1NegotiateMessage::default() => "ff534d4272000000001853c8000000000000000000000000ffff010000000000002200024e54204c4d20302e31320002534d4220322e3030320002534d4220322e3f3f3f00"
98    }
99}