/src/suricata7/rust/src/smb/smb2_ioctl.rs
Line | Count | Source |
1 | | /* Copyright (C) 2018 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 | | use crate::smb::smb::*; |
19 | | use crate::smb::smb2::*; |
20 | | use crate::smb::smb2_records::*; |
21 | | use crate::smb::dcerpc::*; |
22 | | use crate::smb::events::*; |
23 | | #[cfg(feature = "debug")] |
24 | | use crate::smb::funcs::*; |
25 | | use crate::smb::smb_status::*; |
26 | | |
27 | | #[derive(Debug)] |
28 | | pub struct SMBTransactionIoctl { |
29 | | pub func: u32, |
30 | | } |
31 | | |
32 | | impl SMBTransactionIoctl { |
33 | 6.67k | pub fn new(func: u32) -> Self { |
34 | 6.67k | return Self { |
35 | 6.67k | func, |
36 | 6.67k | }; |
37 | 6.67k | } |
38 | | } |
39 | | |
40 | | impl SMBState { |
41 | 6.67k | pub fn new_ioctl_tx(&mut self, hdr: SMBCommonHdr, func: u32) |
42 | 6.67k | -> &mut SMBTransaction |
43 | | { |
44 | 6.67k | let mut tx = self.new_tx(); |
45 | 6.67k | tx.hdr = hdr; |
46 | 6.67k | tx.type_data = Some(SMBTransactionTypeData::IOCTL( |
47 | 6.67k | SMBTransactionIoctl::new(func))); |
48 | 6.67k | tx.request_done = true; |
49 | 6.67k | tx.response_done = self.tc_trunc; // no response expected if tc is truncated |
50 | | |
51 | | SCLogDebug!("SMB: TX IOCTL created: ID {} FUNC {:08x}: {}", |
52 | | tx.id, func, &fsctl_func_to_string(func)); |
53 | 6.67k | self.transactions.push_back(tx); |
54 | 6.67k | let tx_ref = self.transactions.back_mut(); |
55 | 6.67k | return tx_ref.unwrap(); |
56 | 6.67k | } |
57 | | } |
58 | | |
59 | | // IOCTL responses ASYNC don't set the tree id |
60 | 21.7k | pub fn smb2_ioctl_request_record(state: &mut SMBState, r: &Smb2Record) |
61 | | { |
62 | 21.7k | let hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_HEADER); |
63 | 21.7k | match parse_smb2_request_ioctl(r.data) { |
64 | 7.79k | Ok((_, rd)) => { |
65 | | SCLogDebug!("IOCTL request data: {:?}", rd); |
66 | 7.79k | let is_dcerpc = if rd.is_pipe { |
67 | 4.51k | state.get_service_for_guid(rd.guid).1 |
68 | | } else { |
69 | 3.28k | false |
70 | | }; |
71 | 7.79k | if is_dcerpc { |
72 | 1.12k | SCLogDebug!("IOCTL request data is_pipe. Calling smb_write_dcerpc_record"); |
73 | 1.12k | let vercmd = SMBVerCmdStat::new2(SMB2_COMMAND_IOCTL); |
74 | 1.12k | smb_write_dcerpc_record(state, vercmd, hdr, rd.data); |
75 | 6.67k | } else { |
76 | 6.67k | SCLogDebug!("IOCTL {:08x} {}", rd.function, &fsctl_func_to_string(rd.function)); |
77 | 6.67k | let tx = state.new_ioctl_tx(hdr, rd.function); |
78 | 6.67k | tx.vercmd.set_smb2_cmd(SMB2_COMMAND_IOCTL); |
79 | 6.67k | } |
80 | | }, |
81 | 13.9k | _ => { |
82 | 13.9k | let tx = state.new_generic_tx(2, r.command, hdr); |
83 | 13.9k | tx.set_event(SMBEvent::MalformedData); |
84 | 13.9k | }, |
85 | | }; |
86 | 21.7k | } |
87 | | |
88 | | // IOCTL responses ASYNC don't set the tree id |
89 | 30.4k | pub fn smb2_ioctl_response_record(state: &mut SMBState, r: &Smb2Record) |
90 | | { |
91 | 30.4k | let hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_HEADER); |
92 | 30.4k | match parse_smb2_response_ioctl(r.data) { |
93 | 14.8k | Ok((_, rd)) => { |
94 | | SCLogDebug!("IOCTL response data: {:?}", rd); |
95 | | |
96 | 14.8k | let is_dcerpc = if rd.is_pipe { |
97 | 11.6k | state.get_service_for_guid(rd.guid).1 |
98 | | } else { |
99 | 3.13k | false |
100 | | }; |
101 | | // see https://github.com/rust-lang/rust-clippy/issues/15158 |
102 | | #[allow(clippy::collapsible_else_if)] |
103 | 14.8k | if is_dcerpc { |
104 | 7.49k | SCLogDebug!("IOCTL response data is_pipe. Calling smb_read_dcerpc_record"); |
105 | 7.49k | let vercmd = SMBVerCmdStat::new2_with_ntstatus(SMB2_COMMAND_IOCTL, r.nt_status); |
106 | 7.49k | SCLogDebug!("TODO passing empty GUID"); |
107 | 7.49k | smb_read_dcerpc_record(state, vercmd, hdr, &[],rd.data); |
108 | 7.49k | } else { |
109 | | SCLogDebug!("SMB2_COMMAND_IOCTL/SMB_NTSTATUS_PENDING looking for {:?}", hdr); |
110 | 7.32k | if let Some(tx) = state.get_generic_tx(2, SMB2_COMMAND_IOCTL, &hdr) { |
111 | 2.85k | tx.set_status(r.nt_status, false); |
112 | 2.85k | if r.nt_status != SMB_NTSTATUS_PENDING { |
113 | 2.00k | tx.response_done = true; |
114 | 2.00k | } |
115 | 4.47k | } |
116 | | } |
117 | | }, |
118 | | _ => { |
119 | | SCLogDebug!("SMB2_COMMAND_IOCTL/SMB_NTSTATUS_PENDING looking for {:?}", hdr); |
120 | 15.6k | if let Some(tx) = state.get_generic_tx(2, SMB2_COMMAND_IOCTL, &hdr) { |
121 | | SCLogDebug!("updated status of tx {}", tx.id); |
122 | 2.20k | tx.set_status(r.nt_status, false); |
123 | 2.20k | if r.nt_status != SMB_NTSTATUS_PENDING { |
124 | 1.78k | tx.response_done = true; |
125 | 1.78k | } |
126 | | |
127 | | // parsing failed for 'SUCCESS' record, set event |
128 | 2.20k | if r.nt_status == SMB_NTSTATUS_SUCCESS { |
129 | 323 | SCLogDebug!("parse fail {:?}", r); |
130 | 323 | tx.set_event(SMBEvent::MalformedData); |
131 | 1.87k | } |
132 | 13.4k | } |
133 | | }, |
134 | | }; |
135 | 30.4k | } |