smb_server_proto_smb1/
negotiate.rs1#[derive(Debug)]
5pub struct NegotiateReq {
6 pub dialects: Vec<String>,
8}
9
10impl NegotiateReq {
11 pub fn parse(data: &[u8]) -> Self {
14 let mut dialects = Vec::new();
15 let mut i = 0usize;
16 while i < data.len() && data[i] == 0x02 {
17 i += 1;
18 match data[i..].iter().position(|&b| b == 0) {
19 Some(p) => {
20 let end = i + p;
21 dialects.push(String::from_utf8_lossy(&data[i..end]).to_string());
22 i = end + 1;
23 }
24 None => break,
25 }
26 }
27 NegotiateReq { dialects }
28 }
29
30 pub fn select(&self) -> Option<usize> {
32 self.dialects
33 .iter()
34 .position(|d| d.eq_ignore_ascii_case("NT LM 0.12"))
35 }
36}
37
38pub const WORD_COUNT: u8 = 17;
43
44pub fn build_params(dialect_index: u16, caps: u32, now: smb_server_proto::types::FileTime) -> Vec<u8> {
46 let mut p = Vec::with_capacity(34);
47 p.extend_from_slice(&dialect_index.to_le_bytes()); p.push(0x03); p.extend_from_slice(&16u16.to_le_bytes()); p.extend_from_slice(&1u16.to_le_bytes()); p.extend_from_slice(&65535u32.to_le_bytes()); p.extend_from_slice(&65536u32.to_le_bytes()); p.extend_from_slice(&0x1234_5678u32.to_le_bytes()); p.extend_from_slice(&caps.to_le_bytes()); p.extend_from_slice(&now.0.to_le_bytes()); p.extend_from_slice(&0i16.to_le_bytes()); p.push(8u8); debug_assert_eq!(p.len(), 34);
59 p
60}
61
62pub fn build_bytes(challenge: &[u8; 8]) -> Vec<u8> {
64 challenge.to_vec()
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn picks_nt_lm_dialect() {
73 let req = NegotiateReq::parse(
74 b"\x02NT LANMAN 1.0\x00\x02NT LM 0.12\x00",
75 );
76 assert_eq!(req.select().unwrap(), 1);
77 }
78}