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, #[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}