Skip to main content

wireforge_app/smb2/
negotiate.rs

1pub struct Smb2NegotiateRequest<'a> { buf: &'a [u8] }
2impl<'a> Smb2NegotiateRequest<'a> {
3    pub fn parse(buf:&'a[u8])->Option<Self>{
4        if buf.len()<36{return None;}
5        if u16::from_le_bytes([buf[0],buf[1]])!=36{return None;}
6        Some(Self{buf})
7    }
8    pub fn dialect_count(&self)->u16 { u16::from_le_bytes([self.buf[2],self.buf[3]]) }
9    /// Capabilities at offset 8 (4 bytes).
10    pub fn capabilities(&self)->u32 { u32::from_le_bytes(self.buf[8..12].try_into().unwrap()) }
11    /// ClientGuid at offset 12 (16 bytes).
12    pub fn client_guid(&self)->&[u8;16] { self.buf[12..28].try_into().unwrap() }
13    /// Dialects start at offset 36.
14    pub fn dialects(&self)->Vec<u16> {
15        let cnt=self.dialect_count()as usize;
16        (0..cnt).filter_map(|i|{
17            let off=36+i*2;
18            if off+2<=self.buf.len(){Some(u16::from_le_bytes([self.buf[off],self.buf[off+1]]))}else{None}
19        }).collect()
20    }
21}
22
23pub struct Smb2NegotiateResponse<'a> { buf: &'a [u8] }
24impl<'a> Smb2NegotiateResponse<'a> {
25    pub fn parse(buf:&'a[u8])->Option<Self>{
26        if buf.len()<65{return None;}
27        if u16::from_le_bytes([buf[0],buf[1]])!=65{return None;}
28        Some(Self{buf})
29    }
30    /// DialectRevision at offset 4 (2 bytes). SecurityMode at offset 2 (2 bytes).
31    pub fn dialect_revision(&self)->u16 { u16::from_le_bytes([self.buf[4],self.buf[5]]) }
32    /// ServerGuid at offset 8 (16 bytes).
33    pub fn server_guid(&self)->&[u8;16] { self.buf[8..24].try_into().unwrap() }
34    /// Capabilities at offset 24 (4 bytes).
35    pub fn capabilities(&self)->u32 { u32::from_le_bytes(self.buf[24..28].try_into().unwrap()) }
36    pub fn max_transact_size(&self)->u32 { u32::from_le_bytes(self.buf[28..32].try_into().unwrap()) }
37    pub fn max_read_size(&self)->u32 { u32::from_le_bytes(self.buf[32..36].try_into().unwrap()) }
38    pub fn max_write_size(&self)->u32 { u32::from_le_bytes(self.buf[36..40].try_into().unwrap()) }
39    pub fn system_time(&self)->u64 { u64::from_le_bytes(self.buf[40..48].try_into().unwrap()) }
40    pub fn server_start_time(&self)->u64 { u64::from_le_bytes(self.buf[48..56].try_into().unwrap()) }
41}
42
43#[cfg(test)]mod tests{use super::*;
44    #[test]fn parse_negotiate_request(){
45        let mut body=vec![36u8,0,4,0, 0,0, 0,0]; // sz+count+sec_mode+reserved
46        body.extend_from_slice(&1u32.to_le_bytes()); // capabilities (offset 8)
47        body.extend_from_slice(&[0xAAu8;16]); // client_guid (offset 12)
48        body.extend_from_slice(&0u64.to_le_bytes()); // client_start_time (offset 28)
49        body.extend_from_slice(&0x0202u16.to_le_bytes()); // dialects (offset 36)
50        body.extend_from_slice(&0x0210u16.to_le_bytes());
51        body.extend_from_slice(&0x0300u16.to_le_bytes());
52        body.extend_from_slice(&0x0311u16.to_le_bytes());
53        let req=Smb2NegotiateRequest::parse(&body).unwrap();
54        assert_eq!(req.dialect_count(),4);
55        assert_eq!(req.dialects(),vec![0x0202,0x0210,0x0300,0x0311]);
56    }
57    #[test]fn parse_negotiate_response(){
58        let mut body=vec![65u8,0, 0,0, 0x11,0x03, 0,0]; // sz+sec+rev+reserved
59        body.extend_from_slice(&[0u8;16]); // server_guid (offset 8)
60        body.extend_from_slice(&0u32.to_le_bytes()); // capabilities (offset 24)
61        body.extend_from_slice(&65536u32.to_le_bytes()); // max_transact (offset 28)
62        body.extend_from_slice(&65536u32.to_le_bytes()); // max_read (offset 32)
63        body.extend_from_slice(&65536u32.to_le_bytes()); // max_write (offset 36)
64        body.extend_from_slice(&0u64.to_le_bytes()); // system_time (offset 40)
65        body.extend_from_slice(&0u64.to_le_bytes()); // server_start_time (offset 48)
66        body.extend_from_slice(&[0u8;9]); // sec_buf_off+len+reserved2 + 1 byte padding
67        let resp=Smb2NegotiateResponse::parse(&body).unwrap();
68        assert_eq!(resp.dialect_revision(),0x0311);
69        assert_eq!(resp.max_read_size(),65536);
70    }
71}