smb_msg/
session_setup.rs

1use binrw::prelude::*;
2use modular_bitfield::prelude::*;
3
4use smb_dtyp::binrw_util::prelude::*;
5
6#[binrw::binrw]
7#[derive(Debug, PartialEq, Eq)]
8pub struct SessionSetupRequest {
9    #[bw(calc = 25)]
10    #[br(assert(_structure_size == 25))]
11    _structure_size: u16,
12    pub flags: SetupRequestFlags,
13    pub security_mode: SessionSecurityMode,
14    pub capabilities: NegotiateCapabilities,
15    #[bw(calc = 0)]
16    _channel: u32, // reserved
17    #[bw(calc = PosMarker::default())]
18    __security_buffer_offset: PosMarker<u16>,
19    #[bw(calc = u16::try_from(buffer.len()).unwrap())]
20    security_buffer_length: u16,
21    pub previous_session_id: u64,
22    #[br(count = security_buffer_length)]
23    #[bw(write_with = PosMarker::write_aoff, args(&__security_buffer_offset))]
24    pub buffer: Vec<u8>,
25}
26
27#[bitfield]
28#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
29#[bw(map = |&x| Self::into_bytes(x))]
30#[br(map = Self::from_bytes)]
31pub struct SessionSecurityMode {
32    pub signing_enabled: bool,
33    pub signing_required: bool,
34    #[skip]
35    __: B6,
36}
37
38#[bitfield]
39#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
40#[bw(map = |&x| Self::into_bytes(x))]
41#[br(map = Self::from_bytes)]
42pub struct SetupRequestFlags {
43    pub binding: bool,
44    #[skip]
45    __: B7,
46}
47
48#[bitfield]
49#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
50#[bw(map = |&x| Self::into_bytes(x))]
51#[br(map = Self::from_bytes)]
52pub struct NegotiateCapabilities {
53    pub dfs: bool,
54    #[skip]
55    __: B31,
56}
57
58impl SessionSetupRequest {
59    pub fn new(
60        buffer: Vec<u8>,
61        security_mode: SessionSecurityMode,
62        flags: SetupRequestFlags,
63        capabilities: NegotiateCapabilities,
64    ) -> SessionSetupRequest {
65        SessionSetupRequest {
66            flags,
67            security_mode,
68            capabilities,
69            previous_session_id: 0,
70            buffer,
71        }
72    }
73}
74
75#[binrw::binrw]
76#[derive(Debug, PartialEq, Eq)]
77pub struct SessionSetupResponse {
78    #[bw(calc = 9)]
79    #[br(assert(_structure_size == 9))]
80    _structure_size: u16,
81    pub session_flags: SessionFlags,
82    #[bw(calc = PosMarker::default())]
83    _security_buffer_offset: PosMarker<u16>,
84    #[bw(calc = u16::try_from(buffer.len()).unwrap())]
85    security_buffer_length: u16,
86    #[br(count = security_buffer_length)]
87    #[bw(write_with = PosMarker::write_aoff, args(&_security_buffer_offset))]
88    pub buffer: Vec<u8>,
89}
90
91#[bitfield]
92#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
93#[bw(map = |&x| Self::into_bytes(x))]
94#[br(map = Self::from_bytes)]
95pub struct SessionFlags {
96    pub is_guest: bool,
97    pub is_null_session: bool,
98    pub encrypt_data: bool,
99    #[skip]
100    __: B13,
101}
102
103impl SessionFlags {
104    pub fn is_guest_or_null_session(&self) -> bool {
105        self.is_guest() || self.is_null_session()
106    }
107}
108
109#[binrw::binrw]
110#[derive(Debug, Default)]
111pub struct LogoffRequest {
112    #[bw(calc = 4)]
113    #[br(assert(_structure_size == 4))]
114    _structure_size: u16,
115    #[bw(calc = 0)]
116    _reserved: u16,
117}
118
119#[binrw::binrw]
120#[derive(Debug)]
121pub struct LogoffResponse {
122    #[bw(calc = 4)]
123    #[br(assert(_structure_size == 4))]
124    _structure_size: u16,
125    #[bw(calc = 0)]
126    _reserved: u16,
127}
128
129#[cfg(test)]
130mod tests {
131    use smb_tests::*;
132
133    use crate::*;
134
135    use super::*;
136
137    const SETUP_REQUEST_DATA: &'static str = "605706062b0601050502a04d304ba00e300c060a2b06010401823702020aa23904374e544c4d535350000100000097b208e2090009002e00000006000600280000000a005d580000000f41564956564d574f524b47524f5550";
138    test_request! {
139        SessionSetup {
140            flags: SetupRequestFlags::new(),
141            security_mode: SessionSecurityMode::new().with_signing_enabled(true),
142            buffer: hex_to_u8_array! {SETUP_REQUEST_DATA},
143            previous_session_id: 0,
144            capabilities: NegotiateCapabilities::new().with_dfs(true),
145        } => const_format::concatcp!("190000010100000000000000580059000000000000000000", SETUP_REQUEST_DATA)
146    }
147
148    const SETUP_RESPONSE_DATA: &'static str = "a181b03081ada0030a0101a10c060a2b06010401823702020aa281970481944e544c4d53535000020000000c000c003800000015c28ae2abf194bdb756daa9140001000000000050005000440000000a005d580000000f410056004900560056004d0002000c00410056004900560056004d0001000c00410056004900560056004d0004000c00410076006900760056006d0003000c00410076006900760056006d0007000800a876d878c569db0100000000";
149    test_response! {
150        SessionSetup {
151            session_flags: SessionFlags::new(),
152            buffer: hex_to_u8_array! {SETUP_RESPONSE_DATA}
153        } => const_format::concatcp!("090000004800b300", SETUP_RESPONSE_DATA)
154    }
155}