1#[cfg(feature = "server")]
6use binrw::io::TakeSeekExt;
7use binrw::prelude::*;
8
9use smb_dtyp::binrw_util::prelude::*;
10use smb_msg_derive::smb_request_binrw;
11
12#[smb_request_binrw]
17#[brw(little)]
18#[brw(magic(b"\xffSMB"))]
19pub struct SMB1NegotiateMessage {
20 #[bw(calc = 0x72)]
21 #[br(assert(_command == 0x72))]
22 #[br(temp)]
23 _command: u8,
24 status: u32,
25 flags: u8,
26 flags2: u16,
27 #[bw(calc = 0)]
28 #[br(assert(_pid_high == 0))]
29 #[br(temp)]
30 _pid_high: u16,
31 security_features: [u8; 8],
32 reserved: u16,
33 #[bw(calc = 0xffff)]
34 #[br(temp)]
35 _tid: u16,
36 #[bw(calc = 1)]
37 #[br(assert(_pid_low == 1))]
38 #[br(temp)]
39 _pid_low: u16,
40 reserved: u16,
42 reserved: u16,
44 #[bw(calc = 0)]
46 #[br(assert(_word_count == 0))]
47 #[br(temp)]
48 _word_count: u8,
49 byte_count: PosMarker<u16>,
50 #[br(map_stream = |s| s.take_seek(byte_count.value.into()), parse_with = binrw::helpers::until_eof)]
51 #[bw(write_with = PosMarker::write_size, args(byte_count))]
52 dialects: Vec<Smb1Dialect>,
53}
54
55impl SMB1NegotiateMessage {
56 pub fn is_smb2_supported(&self) -> bool {
58 self.dialects
59 .iter()
60 .any(|d| d.name.to_string() == "SMB 2.002")
61 }
62}
63
64impl Default for SMB1NegotiateMessage {
65 fn default() -> Self {
66 Self {
67 status: 0,
68 flags: 0x18,
69 flags2: 0xc853,
70 security_features: [0; 8],
71 byte_count: PosMarker::default(),
72 dialects: vec![
73 Smb1Dialect {
74 name: binrw::NullString::from("NT LM 0.12"),
75 },
76 Smb1Dialect {
77 name: binrw::NullString::from("SMB 2.002"),
78 },
79 Smb1Dialect {
80 name: binrw::NullString::from("SMB 2.???"),
81 },
82 ],
83 }
84 }
85}
86
87#[derive(BinRead, BinWrite, Debug, PartialEq, Eq, Clone)]
89#[brw(magic(b"\x02"))]
90pub struct Smb1Dialect {
91 name: binrw::NullString,
92}
93
94#[cfg(feature = "client")]
95impl TryInto<Vec<u8>> for SMB1NegotiateMessage {
96 type Error = binrw::Error;
97 fn try_into(self) -> Result<Vec<u8>, Self::Error> {
98 let mut buf = std::io::Cursor::new(Vec::new());
99 self.write(&mut buf)?;
100 Ok(buf.into_inner())
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 #[cfg(feature = "client")]
107 use super::*;
108 #[cfg(feature = "client")]
109 smb_tests::test_binrw_write! {
110 SMB1NegotiateMessage: SMB1NegotiateMessage::default() =>
111 "ff534d4272000000001853c8000000000000000000000000ffff010000000000002200024e54204c4d20302e31320002534d4220322e3030320002534d4220322e3f3f3f00"
112 }
113}