]>
Commit | Line | Data |
---|---|---|
d6592211 VJ |
1 | /* Copyright (C) 2017 Open Information Security Foundation |
2 | * | |
3 | * You can copy, redistribute or modify this Program under the terms of | |
4 | * the GNU General Public License version 2 as published by the Free | |
5 | * Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the GNU General Public License | |
13 | * version 2 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
15 | * 02110-1301, USA. | |
16 | */ | |
17 | ||
18 | //! Nom parsers for RPC & NFSv3 | |
19 | ||
42e5065a | 20 | use crate::nfs::nfs_records::*; |
0ffe1233 PC |
21 | use nom7::bytes::streaming::take; |
22 | use nom7::combinator::{complete, cond, rest}; | |
23 | use nom7::multi::{length_data, many0}; | |
24 | use nom7::number::streaming::{be_u32, be_u64}; | |
25 | use nom7::IResult; | |
d6592211 | 26 | |
0ffe1233 | 27 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
28 | pub struct Nfs3Handle<'a> { |
29 | pub len: u32, | |
0ffe1233 | 30 | pub value: &'a [u8], |
d6592211 VJ |
31 | } |
32 | ||
0ffe1233 PC |
33 | pub fn parse_nfs3_handle(i: &[u8]) -> IResult<&[u8], Nfs3Handle> { |
34 | let (i, len) = be_u32(i)?; | |
35 | let (i, value) = take(len as usize)(i)?; | |
36 | let handle = Nfs3Handle { len, value }; | |
37 | Ok((i, handle)) | |
38 | } | |
d6592211 | 39 | |
0ffe1233 | 40 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
41 | pub struct Nfs3ReplyCreate<'a> { |
42 | pub status: u32, | |
43 | pub handle: Option<Nfs3Handle<'a>>, | |
44 | } | |
45 | ||
0ffe1233 PC |
46 | pub fn parse_nfs3_response_create(i: &[u8]) -> IResult<&[u8], Nfs3ReplyCreate> { |
47 | let (i, status) = be_u32(i)?; | |
48 | let (i, handle_has_value) = be_u32(i)?; | |
49 | let (i, handle) = cond(handle_has_value == 1, parse_nfs3_handle)(i)?; | |
50 | let reply = Nfs3ReplyCreate { status, handle }; | |
51 | Ok((i, reply)) | |
52 | } | |
d6592211 | 53 | |
0ffe1233 | 54 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
55 | pub struct Nfs3ReplyLookup<'a> { |
56 | pub status: u32, | |
57 | pub handle: Nfs3Handle<'a>, | |
58 | } | |
59 | ||
0ffe1233 PC |
60 | pub fn parse_nfs3_response_lookup(i: &[u8]) -> IResult<&[u8], Nfs3ReplyLookup> { |
61 | let (i, status) = be_u32(i)?; | |
62 | let (i, handle) = parse_nfs3_handle(i)?; | |
63 | let reply = Nfs3ReplyLookup { status, handle }; | |
64 | Ok((i, reply)) | |
65 | } | |
d6592211 | 66 | |
0ffe1233 | 67 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
68 | pub struct Nfs3RequestCreate<'a> { |
69 | pub handle: Nfs3Handle<'a>, | |
70 | pub name_len: u32, | |
71 | pub create_mode: u32, | |
0ffe1233 | 72 | pub verifier: &'a [u8], |
d6592211 VJ |
73 | pub name_vec: Vec<u8>, |
74 | } | |
75 | ||
0ffe1233 PC |
76 | pub fn parse_nfs3_request_create(i: &[u8]) -> IResult<&[u8], Nfs3RequestCreate> { |
77 | let (i, handle) = parse_nfs3_handle(i)?; | |
78 | let (i, name_len) = be_u32(i)?; | |
79 | let (i, name) = take(name_len as usize)(i)?; | |
80 | let (i, create_mode) = be_u32(i)?; | |
81 | let (i, verifier) = rest(i)?; | |
82 | let req = Nfs3RequestCreate { | |
83 | handle, | |
84 | name_len, | |
85 | create_mode, | |
86 | verifier, | |
87 | name_vec: name.to_vec(), | |
88 | }; | |
89 | Ok((i, req)) | |
90 | } | |
d6592211 | 91 | |
0ffe1233 | 92 | #[derive(Debug, PartialEq)] |
de7e0614 VJ |
93 | pub struct Nfs3RequestRemove<'a> { |
94 | pub handle: Nfs3Handle<'a>, | |
95 | pub name_len: u32, | |
96 | pub name_vec: Vec<u8>, | |
97 | } | |
98 | ||
0ffe1233 PC |
99 | pub fn parse_nfs3_request_remove(i: &[u8]) -> IResult<&[u8], Nfs3RequestRemove> { |
100 | let (i, handle) = parse_nfs3_handle(i)?; | |
101 | let (i, name_len) = be_u32(i)?; | |
102 | let (i, name) = take(name_len as usize)(i)?; | |
103 | let (i, _fill_bytes) = rest(i)?; | |
104 | let req = Nfs3RequestRemove { | |
105 | handle, | |
106 | name_len, | |
107 | name_vec: name.to_vec(), | |
108 | }; | |
109 | Ok((i, req)) | |
110 | } | |
de7e0614 | 111 | |
0ffe1233 | 112 | #[derive(Debug, PartialEq)] |
a116c160 VJ |
113 | pub struct Nfs3RequestRmdir<'a> { |
114 | pub handle: Nfs3Handle<'a>, | |
115 | pub name_vec: Vec<u8>, | |
116 | } | |
117 | ||
0ffe1233 PC |
118 | pub fn parse_nfs3_request_rmdir(i: &[u8]) -> IResult<&[u8], Nfs3RequestRmdir> { |
119 | let (i, handle) = parse_nfs3_handle(i)?; | |
120 | let (i, name_len) = be_u32(i)?; | |
121 | let (i, name) = take(name_len as usize)(i)?; | |
122 | let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?; | |
123 | let req = Nfs3RequestRmdir { | |
124 | handle, | |
125 | name_vec: name.to_vec(), | |
126 | }; | |
127 | Ok((i, req)) | |
128 | } | |
a116c160 | 129 | |
0ffe1233 | 130 | #[derive(Debug, PartialEq)] |
a116c160 VJ |
131 | pub struct Nfs3RequestMkdir<'a> { |
132 | pub handle: Nfs3Handle<'a>, | |
133 | pub name_vec: Vec<u8>, | |
134 | } | |
135 | ||
0ffe1233 PC |
136 | pub fn parse_nfs3_request_mkdir(i: &[u8]) -> IResult<&[u8], Nfs3RequestMkdir> { |
137 | let (i, handle) = parse_nfs3_handle(i)?; | |
138 | let (i, name_len) = be_u32(i)?; | |
139 | let (i, name) = take(name_len as usize)(i)?; | |
140 | let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?; | |
141 | let (i, _attributes) = rest(i)?; | |
142 | let req = Nfs3RequestMkdir { | |
143 | handle, | |
144 | name_vec: name.to_vec(), | |
145 | }; | |
146 | Ok((i, req)) | |
147 | } | |
a116c160 | 148 | |
0ffe1233 | 149 | #[derive(Debug, PartialEq)] |
de7e0614 VJ |
150 | pub struct Nfs3RequestRename<'a> { |
151 | pub from_handle: Nfs3Handle<'a>, | |
152 | pub from_name_vec: Vec<u8>, | |
153 | pub to_handle: Nfs3Handle<'a>, | |
154 | pub to_name_vec: Vec<u8>, | |
155 | } | |
156 | ||
0ffe1233 PC |
157 | pub fn parse_nfs3_request_rename(i: &[u8]) -> IResult<&[u8], Nfs3RequestRename> { |
158 | let (i, from_handle) = parse_nfs3_handle(i)?; | |
159 | let (i, from_name_len) = be_u32(i)?; | |
160 | let (i, from_name) = take(from_name_len as usize)(i)?; | |
161 | let (i, _from_fill_bytes) = cond(from_name_len % 4 != 0, take(4 - (from_name_len % 4)))(i)?; | |
162 | ||
163 | let (i, to_handle) = parse_nfs3_handle(i)?; | |
164 | let (i, to_name_len) = be_u32(i)?; | |
165 | let (i, to_name) = take(to_name_len as usize)(i)?; | |
166 | let (i, _from_fill_bytes) = rest(i)?; | |
167 | let req = Nfs3RequestRename { | |
168 | from_handle, | |
169 | from_name_vec: from_name.to_vec(), | |
170 | to_handle, | |
171 | to_name_vec: to_name.to_vec(), | |
172 | }; | |
173 | Ok((i, req)) | |
174 | } | |
de7e0614 | 175 | |
0ffe1233 | 176 | #[derive(Debug, PartialEq)] |
de7e0614 VJ |
177 | pub struct Nfs3RequestGetAttr<'a> { |
178 | pub handle: Nfs3Handle<'a>, | |
179 | } | |
180 | ||
0ffe1233 PC |
181 | pub fn parse_nfs3_request_getattr(i: &[u8]) -> IResult<&[u8], Nfs3RequestGetAttr> { |
182 | let (i, handle) = parse_nfs3_handle(i)?; | |
183 | Ok((i, Nfs3RequestGetAttr { handle })) | |
184 | } | |
de7e0614 | 185 | |
0ffe1233 | 186 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
187 | pub struct Nfs3RequestAccess<'a> { |
188 | pub handle: Nfs3Handle<'a>, | |
189 | pub check_access: u32, | |
190 | } | |
191 | ||
0ffe1233 PC |
192 | pub fn parse_nfs3_request_access(i: &[u8]) -> IResult<&[u8], Nfs3RequestAccess> { |
193 | let (i, handle) = parse_nfs3_handle(i)?; | |
194 | let (i, check_access) = be_u32(i)?; | |
195 | let req = Nfs3RequestAccess { | |
196 | handle, | |
197 | check_access, | |
198 | }; | |
199 | Ok((i, req)) | |
200 | } | |
d6592211 | 201 | |
0ffe1233 | 202 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
203 | pub struct Nfs3RequestCommit<'a> { |
204 | pub handle: Nfs3Handle<'a>, | |
205 | } | |
206 | ||
0ffe1233 PC |
207 | pub fn parse_nfs3_request_commit(i: &[u8]) -> IResult<&[u8], Nfs3RequestCommit> { |
208 | let (i, handle) = parse_nfs3_handle(i)?; | |
209 | let (i, _offset) = be_u64(i)?; | |
210 | let (i, _count) = be_u32(i)?; | |
211 | Ok((i, Nfs3RequestCommit { handle })) | |
212 | } | |
d6592211 | 213 | |
0ffe1233 | 214 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
215 | pub struct Nfs3RequestRead<'a> { |
216 | pub handle: Nfs3Handle<'a>, | |
217 | pub offset: u64, | |
218 | } | |
219 | ||
0ffe1233 PC |
220 | pub fn parse_nfs3_request_read(i: &[u8]) -> IResult<&[u8], Nfs3RequestRead> { |
221 | let (i, handle) = parse_nfs3_handle(i)?; | |
222 | let (i, offset) = be_u64(i)?; | |
223 | let (i, _count) = be_u32(i)?; | |
224 | Ok((i, Nfs3RequestRead { handle, offset })) | |
225 | } | |
d6592211 | 226 | |
0ffe1233 | 227 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
228 | pub struct Nfs3RequestLookup<'a> { |
229 | pub handle: Nfs3Handle<'a>, | |
230 | ||
231 | pub name_vec: Vec<u8>, | |
232 | } | |
233 | ||
0ffe1233 PC |
234 | pub fn parse_nfs3_request_lookup(i: &[u8]) -> IResult<&[u8], Nfs3RequestLookup> { |
235 | let (i, handle) = parse_nfs3_handle(i)?; | |
236 | let (i, name_contents) = length_data(be_u32)(i)?; | |
237 | let (i, _name_padding) = rest(i)?; | |
238 | let req = Nfs3RequestLookup { | |
239 | handle, | |
240 | name_vec: name_contents.to_vec(), | |
241 | }; | |
242 | Ok((i, req)) | |
243 | } | |
d6592211 | 244 | |
0ffe1233 | 245 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
246 | pub struct Nfs3ResponseReaddirplusEntryC<'a> { |
247 | pub name_vec: Vec<u8>, | |
248 | pub handle: Option<Nfs3Handle<'a>>, | |
249 | } | |
250 | ||
0ffe1233 PC |
251 | pub fn parse_nfs3_response_readdirplus_entry( |
252 | i: &[u8], | |
253 | ) -> IResult<&[u8], Nfs3ResponseReaddirplusEntryC> { | |
254 | let (i, _file_id) = be_u64(i)?; | |
255 | let (i, name_len) = be_u32(i)?; | |
256 | let (i, name_contents) = take(name_len as usize)(i)?; | |
257 | let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?; | |
258 | let (i, _cookie) = take(8_usize)(i)?; | |
259 | let (i, attr_value_follows) = be_u32(i)?; | |
260 | let (i, _attr) = cond(attr_value_follows == 1, take(84_usize))(i)?; | |
261 | let (i, handle_value_follows) = be_u32(i)?; | |
262 | let (i, handle) = cond(handle_value_follows == 1, parse_nfs3_handle)(i)?; | |
263 | let resp = Nfs3ResponseReaddirplusEntryC { | |
264 | name_vec: name_contents.to_vec(), | |
265 | handle, | |
266 | }; | |
267 | Ok((i, resp)) | |
268 | } | |
d6592211 | 269 | |
0ffe1233 | 270 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
271 | pub struct Nfs3ResponseReaddirplusEntry<'a> { |
272 | pub entry: Option<Nfs3ResponseReaddirplusEntryC<'a>>, | |
273 | } | |
274 | ||
0ffe1233 PC |
275 | pub fn parse_nfs3_response_readdirplus_entry_cond( |
276 | i: &[u8], | |
277 | ) -> IResult<&[u8], Nfs3ResponseReaddirplusEntry> { | |
278 | let (i, value_follows) = be_u32(i)?; | |
279 | let (i, entry) = cond(value_follows == 1, parse_nfs3_response_readdirplus_entry)(i)?; | |
280 | Ok((i, Nfs3ResponseReaddirplusEntry { entry })) | |
281 | } | |
d6592211 | 282 | |
0ffe1233 | 283 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
284 | pub struct Nfs3ResponseReaddirplus<'a> { |
285 | pub status: u32, | |
0ffe1233 | 286 | pub data: &'a [u8], |
d6592211 VJ |
287 | } |
288 | ||
0ffe1233 PC |
289 | pub fn parse_nfs3_response_readdirplus(i: &[u8]) -> IResult<&[u8], Nfs3ResponseReaddirplus> { |
290 | let (i, status) = be_u32(i)?; | |
291 | let (i, dir_attr_follows) = be_u32(i)?; | |
292 | let (i, _dir_attr) = cond(dir_attr_follows == 1, take(84_usize))(i)?; | |
293 | let (i, data) = rest(i)?; | |
294 | let resp = Nfs3ResponseReaddirplus { status, data }; | |
295 | Ok((i, resp)) | |
296 | } | |
d6592211 | 297 | |
0ffe1233 PC |
298 | pub(crate) fn many0_nfs3_response_readdirplus_entries<'a>( |
299 | input: &'a [u8], | |
300 | ) -> IResult<&'a [u8], Vec<Nfs3ResponseReaddirplusEntry<'a>>> { | |
301 | many0(complete(parse_nfs3_response_readdirplus_entry_cond))(input) | |
2f08b3ea PC |
302 | } |
303 | ||
0ffe1233 | 304 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
305 | pub struct Nfs3RequestReaddirplus<'a> { |
306 | pub handle: Nfs3Handle<'a>, | |
307 | ||
308 | pub cookie: u32, | |
0ffe1233 | 309 | pub verifier: &'a [u8], |
d6592211 VJ |
310 | pub dircount: u32, |
311 | pub maxcount: u32, | |
312 | } | |
313 | ||
0ffe1233 PC |
314 | pub fn parse_nfs3_request_readdirplus(i: &[u8]) -> IResult<&[u8], Nfs3RequestReaddirplus> { |
315 | let (i, handle) = parse_nfs3_handle(i)?; | |
316 | let (i, cookie) = be_u32(i)?; | |
317 | let (i, verifier) = take(8_usize)(i)?; | |
318 | let (i, dircount) = be_u32(i)?; | |
319 | let (i, maxcount) = be_u32(i)?; | |
320 | let req = Nfs3RequestReaddirplus { | |
321 | handle, | |
322 | cookie, | |
323 | verifier, | |
324 | dircount, | |
325 | maxcount, | |
326 | }; | |
327 | Ok((i, req)) | |
328 | } | |
d6592211 | 329 | |
0ffe1233 | 330 | #[derive(Debug, PartialEq)] |
d6592211 VJ |
331 | pub struct Nfs3RequestWrite<'a> { |
332 | pub handle: Nfs3Handle<'a>, | |
333 | ||
334 | pub offset: u64, | |
335 | pub count: u32, | |
336 | pub stable: u32, | |
337 | pub file_len: u32, | |
0ffe1233 PC |
338 | pub file_data: &'a [u8], |
339 | } | |
340 | ||
341 | pub fn parse_nfs3_request_write(i: &[u8]) -> IResult<&[u8], Nfs3RequestWrite> { | |
342 | let (i, handle) = parse_nfs3_handle(i)?; | |
343 | let (i, offset) = be_u64(i)?; | |
344 | let (i, count) = be_u32(i)?; | |
345 | let (i, stable) = be_u32(i)?; | |
346 | let (i, file_len) = be_u32(i)?; | |
347 | let (i, file_data) = rest(i)?; | |
348 | let req = Nfs3RequestWrite { | |
349 | handle, | |
350 | offset, | |
351 | count, | |
352 | stable, | |
353 | file_len, | |
354 | file_data, | |
355 | }; | |
356 | Ok((i, req)) | |
357 | } | |
9edbb6f2 | 358 | /* |
d6592211 VJ |
359 | #[derive(Debug,PartialEq)] |
360 | pub struct Nfs3ReplyRead<'a> { | |
361 | pub status: u32, | |
362 | pub attr_follows: u32, | |
363 | pub attr_blob: &'a[u8], | |
364 | pub count: u32, | |
365 | pub eof: bool, | |
366 | pub data_len: u32, | |
367 | pub data: &'a[u8], // likely partial | |
368 | } | |
9edbb6f2 | 369 | */ |
0ffe1233 PC |
370 | pub fn parse_nfs3_reply_read(i: &[u8]) -> IResult<&[u8], NfsReplyRead> { |
371 | let (i, status) = be_u32(i)?; | |
372 | let (i, attr_follows) = be_u32(i)?; | |
373 | let (i, attr_blob) = take(84_usize)(i)?; // fixed size? | |
374 | let (i, count) = be_u32(i)?; | |
375 | let (i, eof) = be_u32(i)?; | |
376 | let (i, data_len) = be_u32(i)?; | |
377 | let (i, data) = rest(i)?; | |
378 | let reply = NfsReplyRead { | |
379 | status, | |
380 | attr_follows, | |
381 | attr_blob, | |
382 | count, | |
383 | eof: eof != 0, | |
384 | data_len, | |
385 | data, | |
386 | }; | |
387 | Ok((i, reply)) | |
388 | } |