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