1use 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 #[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}