1use binrw::prelude::*;
4use modular_bitfield::prelude::*;
5
6use smb_dtyp::binrw_util::prelude::*;
7use smb_msg_derive::*;
8
9#[smb_request(size = 25)]
14pub struct SessionSetupRequest {
15 pub flags: SetupRequestFlags,
17 pub security_mode: SessionSecurityMode,
19 pub capabilities: NegotiateCapabilities,
21 reserved: u32,
23 #[bw(calc = PosMarker::default())]
24 #[br(temp)]
25 __security_buffer_offset: PosMarker<u16>,
26 #[bw(calc = u16::try_from(buffer.len()).unwrap())]
27 #[br(temp)]
28 security_buffer_length: u16,
29 pub previous_session_id: u64,
31 #[br(count = security_buffer_length)]
32 #[bw(write_with = PosMarker::write_aoff, args(&__security_buffer_offset))]
33 pub buffer: Vec<u8>,
35}
36
37#[smb_dtyp::mbitfield]
41pub struct SessionSecurityMode {
42 pub signing_enabled: bool,
44 pub signing_required: bool,
46 #[skip]
47 __: B6,
48}
49
50#[smb_dtyp::mbitfield]
54pub struct SetupRequestFlags {
55 pub binding: bool,
57 #[skip]
58 __: B7,
59}
60
61#[smb_dtyp::mbitfield]
65pub struct NegotiateCapabilities {
66 pub dfs: bool,
68 #[skip]
69 __: B31,
70}
71
72impl SessionSetupRequest {
73 pub fn new(
74 buffer: Vec<u8>,
75 security_mode: SessionSecurityMode,
76 flags: SetupRequestFlags,
77 capabilities: NegotiateCapabilities,
78 ) -> SessionSetupRequest {
79 SessionSetupRequest {
80 flags,
81 security_mode,
82 capabilities,
83 previous_session_id: 0,
84 buffer,
85 }
86 }
87}
88
89#[smb_response(size = 9)]
93pub struct SessionSetupResponse {
94 pub session_flags: SessionFlags,
96 #[bw(calc = PosMarker::default())]
97 #[br(temp)]
98 _security_buffer_offset: PosMarker<u16>,
99 #[bw(calc = u16::try_from(buffer.len()).unwrap())]
100 #[br(temp)]
101 security_buffer_length: u16,
102 #[br(count = security_buffer_length)]
103 #[bw(write_with = PosMarker::write_aoff, args(&_security_buffer_offset))]
104 pub buffer: Vec<u8>,
106}
107
108#[smb_dtyp::mbitfield]
112pub struct SessionFlags {
113 pub is_guest: bool,
115 pub is_null_session: bool,
117 pub encrypt_data: bool,
119 #[skip]
120 __: B13,
121}
122
123impl SessionFlags {
124 pub fn is_guest_or_null_session(&self) -> bool {
125 self.is_guest() || self.is_null_session()
126 }
127}
128
129#[smb_request(size = 4)]
133#[derive(Default)]
134pub struct LogoffRequest {
135 reserved: u16,
136}
137
138#[smb_response(size = 4)]
142#[derive(Default)]
143pub struct LogoffResponse {
144 reserved: u16,
145}
146
147#[cfg(test)]
148mod tests {
149 use smb_tests::*;
150
151 use crate::*;
152
153 use super::*;
154
155 const SETUP_REQUEST_DATA: &'static str = "605706062b0601050502a04d304ba00e300c060a2b06010401823702020aa23904374e544c4d535350000100000097b208e2090009002e00000006000600280000000a005d580000000f41564956564d574f524b47524f5550";
156 test_request! {
157 SessionSetup {
158 flags: SetupRequestFlags::new(),
159 security_mode: SessionSecurityMode::new().with_signing_enabled(true),
160 buffer: hex_to_u8_array! {SETUP_REQUEST_DATA},
161 previous_session_id: 0,
162 capabilities: NegotiateCapabilities::new().with_dfs(true),
163 } => const_format::concatcp!("190000010100000000000000580059000000000000000000", SETUP_REQUEST_DATA)
164 }
165
166 const SETUP_RESPONSE_DATA: &'static str = "a181b03081ada0030a0101a10c060a2b06010401823702020aa281970481944e544c4d53535000020000000c000c003800000015c28ae2abf194bdb756daa9140001000000000050005000440000000a005d580000000f410056004900560056004d0002000c00410056004900560056004d0001000c00410056004900560056004d0004000c00410076006900760056006d0003000c00410076006900760056006d0007000800a876d878c569db0100000000";
167 test_response! {
168 SessionSetup {
169 session_flags: SessionFlags::new(),
170 buffer: hex_to_u8_array! {SETUP_RESPONSE_DATA}
171 } => const_format::concatcp!("090000004800b300", SETUP_RESPONSE_DATA)
172 }
173}