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)]
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    ) -> SessionSetupRequest {
64        SessionSetupRequest {
65            flags,
66            security_mode,
67            capabilities: NegotiateCapabilities::new().with_dfs(true),
68            previous_session_id: 0,
69            buffer,
70        }
71    }
72}
73
74#[binrw::binrw]
75#[derive(Debug, PartialEq, Eq)]
76pub struct SessionSetupResponse {
77    #[bw(calc = 9)]
78    #[br(assert(_structure_size == 9))]
79    _structure_size: u16,
80    pub session_flags: SessionFlags,
81    #[bw(calc = PosMarker::default())]
82    _security_buffer_offset: PosMarker<u16>,
83    #[bw(calc = u16::try_from(buffer.len()).unwrap())]
84    security_buffer_length: u16,
85    #[br(count = security_buffer_length)]
86    #[bw(write_with = PosMarker::write_aoff, args(&_security_buffer_offset))]
87    pub buffer: Vec<u8>,
88}
89
90#[bitfield]
91#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
92#[bw(map = |&x| Self::into_bytes(x))]
93#[br(map = Self::from_bytes)]
94pub struct SessionFlags {
95    pub is_guest: bool,
96    pub is_null_session: bool,
97    pub encrypt_data: bool,
98    #[skip]
99    __: B13,
100}
101
102impl SessionFlags {
103    pub fn is_guest_or_null_session(&self) -> bool {
104        self.is_guest() || self.is_null_session()
105    }
106}
107
108#[binrw::binrw]
109#[derive(Debug, Default)]
110pub struct LogoffRequest {
111    #[bw(calc = 4)]
112    #[br(assert(_structure_size == 4))]
113    _structure_size: u16,
114    #[bw(calc = 0)]
115    _reserved: u16,
116}
117
118#[binrw::binrw]
119#[derive(Debug)]
120pub struct LogoffResponse {
121    #[bw(calc = 4)]
122    #[br(assert(_structure_size == 4))]
123    _structure_size: u16,
124    #[bw(calc = 0)]
125    _reserved: u16,
126}
127
128#[cfg(test)]
129mod tests {
130    use crate::*;
131
132    use super::*;
133
134    #[test]
135    pub fn test_setup_req_write() {
136        let data = encode_content(
137            SessionSetupRequest::new(
138                [
139                    0x60, 0x57, 0x6, 0x6, 0x2b, 0x6, 0x1, 0x5, 0x5, 0x2, 0xa0, 0x4d, 0x30, 0x4b,
140                    0xa0, 0xe, 0x30, 0xc, 0x6, 0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37, 0x2, 0x2,
141                    0xa, 0xa2, 0x39, 0x4, 0x37, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x0, 0x1,
142                    0x0, 0x0, 0x0, 0x97, 0xb2, 0x8, 0xe2, 0x9, 0x0, 0x9, 0x0, 0x2e, 0x0, 0x0, 0x0,
143                    0x6, 0x0, 0x6, 0x0, 0x28, 0x0, 0x0, 0x0, 0xa, 0x0, 0x5d, 0x58, 0x0, 0x0, 0x0,
144                    0xf, 0x41, 0x56, 0x49, 0x56, 0x56, 0x4d, 0x57, 0x4f, 0x52, 0x4b, 0x47, 0x52,
145                    0x4f, 0x55, 0x50,
146                ]
147                .to_vec(),
148                SessionSecurityMode::new().with_signing_enabled(true),
149                SetupRequestFlags::new(),
150            )
151            .into(),
152        );
153
154        assert_eq!(
155            data,
156            [
157                0x19, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x58, 0x0, 0x59, 0x0,
158                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x57, 0x6, 0x6, 0x2b, 0x6, 0x1, 0x5,
159                0x5, 0x2, 0xa0, 0x4d, 0x30, 0x4b, 0xa0, 0xe, 0x30, 0xc, 0x6, 0xa, 0x2b, 0x6, 0x1,
160                0x4, 0x1, 0x82, 0x37, 0x2, 0x2, 0xa, 0xa2, 0x39, 0x4, 0x37, 0x4e, 0x54, 0x4c, 0x4d,
161                0x53, 0x53, 0x50, 0x0, 0x1, 0x0, 0x0, 0x0, 0x97, 0xb2, 0x8, 0xe2, 0x9, 0x0, 0x9,
162                0x0, 0x2e, 0x0, 0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0x28, 0x0, 0x0, 0x0, 0xa, 0x0, 0x5d,
163                0x58, 0x0, 0x0, 0x0, 0xf, 0x41, 0x56, 0x49, 0x56, 0x56, 0x4d, 0x57, 0x4f, 0x52,
164                0x4b, 0x47, 0x52, 0x4f, 0x55, 0x50,
165            ],
166        )
167    }
168
169    #[test]
170    pub fn test_setup_resp_parse() {
171        let data = [
172            0xfe, 0x53, 0x4d, 0x42, 0x40, 0x0, 0x1, 0x0, 0x16, 0x0, 0x0, 0xc0, 0x1, 0x0, 0x1, 0x0,
173            0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
174            0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x28, 0x0, 0x30, 0x0, 0x0, 0x0,
175            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x0,
176            0x0, 0x0, 0x48, 0x0, 0xb3, 0x0, 0xa1, 0x81, 0xb0, 0x30, 0x81, 0xad, 0xa0, 0x3, 0xa,
177            0x1, 0x1, 0xa1, 0xc, 0x6, 0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37, 0x2, 0x2, 0xa,
178            0xa2, 0x81, 0x97, 0x4, 0x81, 0x94, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x0, 0x2,
179            0x0, 0x0, 0x0, 0xc, 0x0, 0xc, 0x0, 0x38, 0x0, 0x0, 0x0, 0x15, 0xc2, 0x8a, 0xe2, 0xab,
180            0xf1, 0x94, 0xbd, 0xb7, 0x56, 0xda, 0xa9, 0x14, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
181            0x50, 0x0, 0x50, 0x0, 0x44, 0x0, 0x0, 0x0, 0xa, 0x0, 0x5d, 0x58, 0x0, 0x0, 0x0, 0xf,
182            0x41, 0x0, 0x56, 0x0, 0x49, 0x0, 0x56, 0x0, 0x56, 0x0, 0x4d, 0x0, 0x2, 0x0, 0xc, 0x0,
183            0x41, 0x0, 0x56, 0x0, 0x49, 0x0, 0x56, 0x0, 0x56, 0x0, 0x4d, 0x0, 0x1, 0x0, 0xc, 0x0,
184            0x41, 0x0, 0x56, 0x0, 0x49, 0x0, 0x56, 0x0, 0x56, 0x0, 0x4d, 0x0, 0x4, 0x0, 0xc, 0x0,
185            0x41, 0x0, 0x76, 0x0, 0x69, 0x0, 0x76, 0x0, 0x56, 0x0, 0x6d, 0x0, 0x3, 0x0, 0xc, 0x0,
186            0x41, 0x0, 0x76, 0x0, 0x69, 0x0, 0x76, 0x0, 0x56, 0x0, 0x6d, 0x0, 0x7, 0x0, 0x8, 0x0,
187            0xa8, 0x76, 0xd8, 0x78, 0xc5, 0x69, 0xdb, 0x1, 0x0, 0x0, 0x0, 0x0,
188        ];
189
190        let response = decode_content(&data).content.to_sessionsetup().unwrap();
191
192        assert_eq!(
193            response,
194            SessionSetupResponse {
195                session_flags: SessionFlags::new(),
196                buffer: [
197                    0xa1, 0x81, 0xb0, 0x30, 0x81, 0xad, 0xa0, 0x3, 0xa, 0x1, 0x1, 0xa1, 0xc, 0x6,
198                    0xa, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37, 0x2, 0x2, 0xa, 0xa2, 0x81, 0x97,
199                    0x4, 0x81, 0x94, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x0, 0x2, 0x0, 0x0,
200                    0x0, 0xc, 0x0, 0xc, 0x0, 0x38, 0x0, 0x0, 0x0, 0x15, 0xc2, 0x8a, 0xe2, 0xab,
201                    0xf1, 0x94, 0xbd, 0xb7, 0x56, 0xda, 0xa9, 0x14, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0,
202                    0x0, 0x50, 0x0, 0x50, 0x0, 0x44, 0x0, 0x0, 0x0, 0xa, 0x0, 0x5d, 0x58, 0x0, 0x0,
203                    0x0, 0xf, 0x41, 0x0, 0x56, 0x0, 0x49, 0x0, 0x56, 0x0, 0x56, 0x0, 0x4d, 0x0,
204                    0x2, 0x0, 0xc, 0x0, 0x41, 0x0, 0x56, 0x0, 0x49, 0x0, 0x56, 0x0, 0x56, 0x0,
205                    0x4d, 0x0, 0x1, 0x0, 0xc, 0x0, 0x41, 0x0, 0x56, 0x0, 0x49, 0x0, 0x56, 0x0,
206                    0x56, 0x0, 0x4d, 0x0, 0x4, 0x0, 0xc, 0x0, 0x41, 0x0, 0x76, 0x0, 0x69, 0x0,
207                    0x76, 0x0, 0x56, 0x0, 0x6d, 0x0, 0x3, 0x0, 0xc, 0x0, 0x41, 0x0, 0x76, 0x0,
208                    0x69, 0x0, 0x76, 0x0, 0x56, 0x0, 0x6d, 0x0, 0x7, 0x0, 0x8, 0x0, 0xa8, 0x76,
209                    0xd8, 0x78, 0xc5, 0x69, 0xdb, 0x1, 0x0, 0x0, 0x0, 0x0
210                ]
211                .to_vec()
212            }
213        )
214    }
215}