]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/nfs/nfs3.rs
rust/nfs: convert parser to nom7 functions (NFS v2 records)
[people/ms/suricata.git] / rust / src / nfs / nfs3.rs
CommitLineData
74305c04 1/* Copyright (C) 2017-2020 Open Information Security Foundation
9b42073e
VJ
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// written by Victor Julien
19
42e5065a 20use crate::core::*;
9b42073e 21
42e5065a
JI
22use crate::nfs::nfs::*;
23use crate::nfs::types::*;
24use crate::nfs::rpc_records::*;
25use crate::nfs::nfs3_records::*;
9b42073e 26
acb3ec6d
PC
27use nom7::IResult;
28use nom7::number::streaming::be_u32;
5b809f77 29
9b42073e
VJ
30impl NFSState {
31 /// complete NFS3 request record
66598f9c 32 pub fn process_request_record_v3<'b>(&mut self, r: &RpcPacket<'b>) {
9b42073e
VJ
33 SCLogDebug!("REQUEST {} procedure {} ({}) blob size {}",
34 r.hdr.xid, r.procedure, self.requestmap.len(), r.prog_data.len());
35
36 let mut xidmap = NFSRequestXidMap::new(r.progver, r.procedure, 0);
37 let mut aux_file_name = Vec::new();
38
39 if self.nfs_version == 0 {
40 self.nfs_version = r.progver as u16;
41 }
42
43 if r.procedure == NFSPROC3_LOOKUP {
44 self.process_request_record_lookup(r, &mut xidmap);
45
46 } else if r.procedure == NFSPROC3_ACCESS {
6ae66cb2
VJ
47 if let Ok((_, rd)) = parse_nfs3_request_access(r.prog_data) {
48 xidmap.file_handle = rd.handle.value.to_vec();
49 self.xidmap_handle2name(&mut xidmap);
50 } else {
51 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
52 };
53 } else if r.procedure == NFSPROC3_GETATTR {
6ae66cb2
VJ
54 if let Ok((_, rd)) = parse_nfs3_request_getattr(r.prog_data) {
55 xidmap.file_handle = rd.handle.value.to_vec();
56 self.xidmap_handle2name(&mut xidmap);
57 } else {
58 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
59 };
60 } else if r.procedure == NFSPROC3_READDIRPLUS {
6ae66cb2
VJ
61 if let Ok((_, rd)) = parse_nfs3_request_readdirplus(r.prog_data) {
62 xidmap.file_handle = rd.handle.value.to_vec();
63 self.xidmap_handle2name(&mut xidmap);
64 } else {
65 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
66 };
67 } else if r.procedure == NFSPROC3_READ {
6ae66cb2
VJ
68 if let Ok((_, rd)) = parse_nfs3_request_read(r.prog_data) {
69 xidmap.chunk_offset = rd.offset;
70 xidmap.file_handle = rd.handle.value.to_vec();
71 self.xidmap_handle2name(&mut xidmap);
72 } else {
73 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
74 };
75 } else if r.procedure == NFSPROC3_WRITE {
6ae66cb2
VJ
76 if let Ok((_, rd)) = parse_nfs3_request_write(r.prog_data) {
77 self.process_write_record(r, &rd);
78 } else {
79 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
80 }
81 } else if r.procedure == NFSPROC3_CREATE {
6ae66cb2
VJ
82 if let Ok((_, rd)) = parse_nfs3_request_create(r.prog_data) {
83 xidmap.file_handle = rd.handle.value.to_vec();
84 xidmap.file_name = rd.name_vec;
85 } else {
86 self.set_event(NFSEvent::MalformedData);
9b42073e 87 };
9b42073e 88 } else if r.procedure == NFSPROC3_REMOVE {
6ae66cb2
VJ
89 if let Ok((_, rd)) = parse_nfs3_request_remove(r.prog_data) {
90 xidmap.file_handle = rd.handle.value.to_vec();
91 xidmap.file_name = rd.name_vec;
92 } else {
93 self.set_event(NFSEvent::MalformedData);
9b42073e 94 };
9b42073e 95 } else if r.procedure == NFSPROC3_RENAME {
6ae66cb2
VJ
96 if let Ok((_, rd)) = parse_nfs3_request_rename(r.prog_data) {
97 xidmap.file_handle = rd.from_handle.value.to_vec();
98 xidmap.file_name = rd.from_name_vec;
99 aux_file_name = rd.to_name_vec;
100 } else {
101 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
102 };
103 } else if r.procedure == NFSPROC3_MKDIR {
6ae66cb2
VJ
104 if let Ok((_, rd)) = parse_nfs3_request_mkdir(r.prog_data) {
105 xidmap.file_handle = rd.handle.value.to_vec();
106 xidmap.file_name = rd.name_vec;
107 } else {
108 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
109 };
110 } else if r.procedure == NFSPROC3_RMDIR {
6ae66cb2
VJ
111 if let Ok((_, rd)) = parse_nfs3_request_rmdir(r.prog_data) {
112 xidmap.file_handle = rd.handle.value.to_vec();
113 xidmap.file_name = rd.name_vec;
114 } else {
115 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
116 };
117 } else if r.procedure == NFSPROC3_COMMIT {
118 SCLogDebug!("COMMIT, closing shop");
6ae66cb2
VJ
119 if let Ok((_, rd)) = parse_nfs3_request_commit(r.prog_data) {
120 let file_handle = rd.handle.value.to_vec();
11c438a0 121 if let Some((tx, files, flags)) = self.get_file_tx_by_handle(&file_handle, Direction::ToServer) {
6ae66cb2
VJ
122 if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
123 tdf.chunk_count += 1;
124 tdf.file_additional_procs.push(NFSPROC3_COMMIT);
125 tdf.file_tracker.close(files, flags);
126 tdf.file_last_xid = r.hdr.xid;
127 tx.is_last = true;
128 tx.request_done = true;
67759795 129 tx.is_file_closed = true;
9b42073e 130 }
6ae66cb2
VJ
131 }
132 } else {
133 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
134 };
135 }
136
137 if !(r.procedure == NFSPROC3_COMMIT || // commit handled separately
138 r.procedure == NFSPROC3_WRITE || // write handled in file tx
139 r.procedure == NFSPROC3_READ) // read handled in file tx at reply
140 {
141 let mut tx = self.new_tx();
142 tx.xid = r.hdr.xid;
143 tx.procedure = r.procedure;
144 tx.request_done = true;
145 tx.file_name = xidmap.file_name.to_vec();
146 tx.nfs_version = r.progver as u16;
147 tx.file_handle = xidmap.file_handle.to_vec();
148
149 if r.procedure == NFSPROC3_RENAME {
150 tx.type_data = Some(NFSTransactionTypeData::RENAME(aux_file_name));
151 }
152
153 tx.auth_type = r.creds_flavor;
154 match r.creds {
155 RpcRequestCreds::Unix(ref u) => {
156 tx.request_machine_name = u.machine_name_buf.to_vec();
157 tx.request_uid = u.uid;
158 tx.request_gid = u.gid;
159 },
160 _ => { },
161 }
162 SCLogDebug!("TX created: ID {} XID {} PROCEDURE {}",
163 tx.id, tx.xid, tx.procedure);
164 self.transactions.push(tx);
165
166 } else if r.procedure == NFSPROC3_READ {
167
11c438a0 168 let found = match self.get_file_tx_by_handle(&xidmap.file_handle, Direction::ToClient) {
9b42073e
VJ
169 Some((_, _, _)) => true,
170 None => false,
171 };
172 if !found {
11c438a0 173 let (tx, _, _) = self.new_file_tx(&xidmap.file_handle, &xidmap.file_name, Direction::ToClient);
9b42073e
VJ
174 tx.procedure = NFSPROC3_READ;
175 tx.xid = r.hdr.xid;
176 tx.is_first = true;
177 tx.nfs_version = r.progver as u16;
178
179 tx.auth_type = r.creds_flavor;
6ae66cb2
VJ
180 if let RpcRequestCreds::Unix(ref u) = r.creds {
181 tx.request_machine_name = u.machine_name_buf.to_vec();
182 tx.request_uid = u.uid;
183 tx.request_gid = u.gid;
9b42073e
VJ
184 }
185 }
186 }
187
188 self.requestmap.insert(r.hdr.xid, xidmap);
9b42073e
VJ
189 }
190
66598f9c 191 pub fn process_reply_record_v3<'b>(&mut self, r: &RpcReplyPacket<'b>, xidmap: &mut NFSRequestXidMap) {
9b42073e
VJ
192 let mut nfs_status = 0;
193 let mut resp_handle = Vec::new();
194
195 if xidmap.procedure == NFSPROC3_LOOKUP {
6ae66cb2
VJ
196 if let Ok((_, rd)) = parse_nfs3_response_lookup(r.prog_data) {
197 SCLogDebug!("LOOKUP: {:?}", rd);
198 SCLogDebug!("RESPONSE LOOKUP file_name {:?}", xidmap.file_name);
9b42073e 199
6ae66cb2 200 nfs_status = rd.status;
9b42073e 201
6ae66cb2
VJ
202 SCLogDebug!("LOOKUP handle {:?}", rd.handle);
203 self.namemap.insert(rd.handle.value.to_vec(), xidmap.file_name.to_vec());
204 resp_handle = rd.handle.value.to_vec();
205 } else {
206 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
207 };
208 } else if xidmap.procedure == NFSPROC3_CREATE {
6ae66cb2
VJ
209 if let Ok((_, rd)) = parse_nfs3_response_create(r.prog_data) {
210 SCLogDebug!("nfs3_create_record: {:?}", rd);
211 SCLogDebug!("RESPONSE CREATE file_name {:?}", xidmap.file_name);
212 nfs_status = rd.status;
9b42073e 213
6ae66cb2
VJ
214 if let Some(h) = rd.handle {
215 SCLogDebug!("handle {:?}", h);
216 self.namemap.insert(h.value.to_vec(), xidmap.file_name.to_vec());
217 resp_handle = h.value.to_vec();
218 }
219 } else {
220 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
221 };
222 } else if xidmap.procedure == NFSPROC3_READ {
6ae66cb2 223 if let Ok((_, rd)) = parse_nfs3_reply_read(r.prog_data) {
69cf5c9e 224 self.process_read_record(r, &rd, Some(xidmap));
6ae66cb2
VJ
225 nfs_status = rd.status;
226 } else {
227 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
228 }
229 } else if xidmap.procedure == NFSPROC3_READDIRPLUS {
6ae66cb2
VJ
230 if let Ok((_, rd)) = parse_nfs3_response_readdirplus(r.prog_data) {
231 nfs_status = rd.status;
9b42073e 232
6ae66cb2
VJ
233 // cut off final eof field
234 let d = if rd.data.len() >= 4 {
235 &rd.data[..rd.data.len()-4 as usize]
236 } else {
237 rd.data
238 };
9b42073e 239
6ae66cb2
VJ
240 // store all handle/filename mappings
241 if let Ok((_, ref entries)) = many0_nfs3_response_readdirplus_entries(d) {
242 SCLogDebug!("READDIRPLUS ENTRIES reply {:?}", entries);
243 for ce in entries {
244 SCLogDebug!("ce {:?}", ce);
245 if let Some(ref e) = ce.entry {
246 SCLogDebug!("e {:?}", e);
247 if let Some(ref h) = e.handle {
248 SCLogDebug!("h {:?}", h);
249 self.namemap.insert(h.value.to_vec(),
250 e.name_vec.to_vec());
9b42073e 251 }
6ae66cb2 252 }
9b42073e 253 }
6ae66cb2 254 } else {
9b42073e 255 self.set_event(NFSEvent::MalformedData);
6ae66cb2
VJ
256 }
257 } else {
258 self.set_event(NFSEvent::MalformedData);
9b42073e
VJ
259 }
260 }
261 // for all other record types only parse the status
262 else {
69cf5c9e 263 let stat : u32 = match be_u32(r.prog_data) as IResult<&[u8],_> {
6ae66cb2
VJ
264 Ok((_, stat)) => stat,
265 _ => 0
9b42073e
VJ
266 };
267 nfs_status = stat;
268 }
269 SCLogDebug!("REPLY {} to procedure {} blob size {}",
270 r.hdr.xid, xidmap.procedure, r.prog_data.len());
271
272 if xidmap.procedure != NFSPROC3_READ {
273 self.mark_response_tx_done(r.hdr.xid, r.reply_state, nfs_status, &resp_handle);
274 }
9b42073e 275 }
9b42073e 276}