smb_server_proto_smb1/
trans2.rs1use smb_server_proto::buf::Reader;
7
8pub mod subcmd {
10 pub const FIND_FIRST2: u8 = 0x01;
12 pub const FIND_NEXT2: u8 = 0x02;
14 pub const QUERY_FS_INFO: u8 = 0x03;
16 pub const SET_FS_INFO: u8 = 0x04;
18 pub const QUERY_PATH_INFO: u8 = 0x05;
20 pub const SET_PATH_INFO: u8 = 0x06;
22 pub const QUERY_FILE_INFO: u8 = 0x07;
24 pub const SET_FILE_INFO: u8 = 0x08;
26}
27
28pub mod level {
30 pub const BASIC: u16 = 0x004;
32 pub const STANDARD: u16 = 0x005;
34 pub const EA_SIZE: u16 = 0x006;
36 pub const STREAMS: u16 = 0x010;
38 pub const PT_BASIC: u16 = 0x1004;
40 pub const PT_STANDARD: u16 = 0x1005;
42 pub const PT_INTERNAL: u16 = 0x1006;
44 pub const PT_EA: u16 = 0x1007;
46 pub const PT_NAME: u16 = 0x1009;
48 pub const PT_ALLOC: u16 = 0x100B;
50 pub const PT_EOF: u16 = 0x100C;
52 pub const PT_DISPOSITION: u16 = 0x100D;
54 pub const PT_ALL: u16 = 0x1012;
56 pub const PT_ALT_NAME: u16 = 0x1015;
58 pub const ATTRIBUTE_COMPOSITE: u16 = 0x107;
60}
61
62pub mod find_level {
64 pub const STANDARD: u16 = 0x001;
66 pub const DIRECTORY: u16 = 0x102;
68 pub const FULL: u16 = 0x103;
70 pub const BOTH: u16 = 0x104;
72 pub const NAMES: u16 = 0x105;
74}
75
76#[derive(Debug)]
79pub struct Trans2Req {
80 pub subcmd: u8,
82 pub params: Vec<u8>,
84 pub data: Vec<u8>,
86 pub param_base: usize,
88 pub data_base: usize,
90 pub unicode: bool,
92}
93
94impl Trans2Req {
95 pub fn parse(
103 _wct: u8,
104 words: &[u8],
105 buf: &[u8],
106 _bc_off_abs: usize,
107 unicode: bool,
108 ) -> Option<Trans2Req> {
109 if words.len() < 30 {
110 return None;
111 }
112 let g = |i: usize| -> u16 {
113 if i + 2 <= words.len() {
114 u16::from_le_bytes([words[i], words[i + 1]])
115 } else {
116 0
117 }
118 };
119 let pcount = g(18) as usize; let poff = g(20) as usize; let dcount = g(24) as usize; let doff = g(26) as usize; if poff > buf.len() || poff + pcount > buf.len() {
125 return None;
126 }
127 let params_all = &buf[poff..poff + pcount];
128 if params_all.is_empty() {
129 return None;
130 }
131 let setup_count = *words.get(26)? as usize;
132 let (subcmd, fixed, param_base) = if setup_count >= 1 {
133 let sc = *words.get(28).unwrap_or(¶ms_all[0]);
135 (sc, params_all.to_vec(), poff)
136 } else if pcount >= 2 {
137 (params_all[0], params_all[2..].to_vec(), poff + 2)
139 } else {
140 return None;
141 };
142
143 let mut dcount = dcount;
146 if doff > buf.len() || doff + dcount > buf.len() {
147 dcount = buf.len().saturating_sub(doff).min(dcount);
148 }
149 let data: Vec<u8> = if dcount > 0 && doff >= HDR_ABS_MIN && doff + dcount <= buf.len() {
150 buf[doff..doff + dcount].to_vec()
151 } else {
152 Vec::new()
153 };
154
155 Some(Trans2Req {
156 subcmd,
157 params: fixed,
158 data,
159 param_base,
160 data_base: doff,
161 unicode,
162 })
163 }
164}
165
166const HDR_ABS_MIN: usize = 32;
168
169pub fn trans2_resp(params: Vec<u8>, data: Vec<u8>) -> (Vec<u8>, Vec<u8>) {
172 const WORDS_BYTES: usize = 20;
173 const BC_START: usize = 32 + 1 + WORDS_BYTES + 2; let plen = params.len();
176 let dlen = data.len();
177 let poff = if plen > 0 { (BC_START + 1) & !1 } else { 0 };
178 let raw_doff = if plen > 0 { poff + plen } else { BC_START };
179 let doff = if dlen > 0 { (raw_doff + 1) & !1 } else { 0 };
180
181 let mut p = Vec::with_capacity(WORDS_BYTES);
182 p.extend_from_slice(&(plen as u16).to_le_bytes()); p.extend_from_slice(&(dlen as u16).to_le_bytes()); p.extend_from_slice(&0u16.to_le_bytes()); p.extend_from_slice(&(plen as u16).to_le_bytes()); p.extend_from_slice(&(poff as u16).to_le_bytes()); p.extend_from_slice(&0u16.to_le_bytes()); p.extend_from_slice(&(dlen as u16).to_le_bytes()); p.extend_from_slice(&(doff as u16).to_le_bytes()); p.extend_from_slice(&0u16.to_le_bytes()); p.push(0); p.push(0); debug_assert_eq!(p.len(), WORDS_BYTES);
195
196 let mut bytes = Vec::new();
197 if plen > 0 {
198 bytes.resize(poff - BC_START, 0);
199 bytes.extend_from_slice(¶ms);
200 }
201 if dlen > 0 {
202 bytes.resize(doff - BC_START, 0);
203 bytes.extend_from_slice(&data);
204 }
205 (p, bytes)
206}
207
208pub fn read_param_zstring<'a>(
211 rd: &mut Reader<'a>,
212 _pos: usize,
213 param_base: usize,
214 unicode: bool,
215) -> String {
216 rd.zstring(unicode, param_base)
217}