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 #[br(assert(_reserved == 0))]
27 _reserved: u16,
28 #[bw(calc = 0xffff)]
29 _tid: u16,
30 #[bw(calc = 1)]
31 #[br(assert(_pid_low == 1))]
32 _pid_low: u16,
33 #[bw(calc = 0)]
34 _uid: u16,
35 #[bw(calc = 0)]
36 _mid: u16,
37 #[bw(calc = 0)]
39 #[br(assert(_word_count == 0))]
40 _word_count: u8,
41 byte_count: PosMarker<u16>,
42 #[br(map_stream = |s| s.take_seek(byte_count.value.into()), parse_with = binrw::helpers::until_eof)]
43 #[bw(write_with = PosMarker::write_size, args(byte_count))]
44 dialects: Vec<Smb1Dialect>,
45}
46
47impl SMB1NegotiateMessage {
48 pub fn is_smb2_supported(&self) -> bool {
49 self.dialects
50 .iter()
51 .any(|d| d.name.to_string() == "SMB 2.002")
52 }
53}
54
55impl Default for SMB1NegotiateMessage {
56 fn default() -> Self {
57 Self {
58 status: 0,
59 flags: 0x18,
60 flags2: 0xc853,
61 security_features: [0; 8],
62 byte_count: PosMarker::default(),
63 dialects: vec![
64 Smb1Dialect {
65 name: binrw::NullString::from("NT LM 0.12"),
66 },
67 Smb1Dialect {
68 name: binrw::NullString::from("SMB 2.002"),
69 },
70 Smb1Dialect {
71 name: binrw::NullString::from("SMB 2.???"),
72 },
73 ],
74 }
75 }
76}
77
78#[derive(BinRead, BinWrite, Debug)]
79#[brw(magic(b"\x02"))]
80pub struct Smb1Dialect {
81 name: binrw::NullString,
82}
83
84impl TryInto<Vec<u8>> for SMB1NegotiateMessage {
85 type Error = binrw::Error;
86 fn try_into(self) -> Result<Vec<u8>, Self::Error> {
87 let mut buf = std::io::Cursor::new(Vec::new());
88 self.write(&mut buf)?;
89 Ok(buf.into_inner())
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 pub fn test_smb1_negotiate_req_write() {
99 let msg = SMB1NegotiateMessage::default();
100 let buf: Result<Vec<u8>, binrw::Error> = msg.try_into();
101 assert_eq!(
102 buf.unwrap(),
103 [
104 0xff, 0x53, 0x4d, 0x42, 0x72, 0x0, 0x0, 0x0, 0x0, 0x18, 0x53, 0xc8, 0x0, 0x0, 0x0,
105 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x01, 0x00, 0x0, 0x0, 0x0,
106 0x0, 0x0, 0x22, 0x0, 0x2, 0x4e, 0x54, 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31,
107 0x32, 0x0, 0x2, 0x53, 0x4d, 0x42, 0x20, 0x32, 0x2e, 0x30, 0x30, 0x32, 0x0, 0x2,
108 0x53, 0x4d, 0x42, 0x20, 0x32, 0x2e, 0x3f, 0x3f, 0x3f, 0x0
109 ]
110 )
111 }
112}