/src/suricata7/rust/src/smb/detect.rs
Line | Count | Source |
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 | | use std::ptr; |
19 | | use crate::core::*; |
20 | | use crate::smb::smb::*; |
21 | | use crate::dcerpc::detect::{DCEIfaceData, DCEOpnumData, DETECT_DCE_OPNUM_RANGE_UNINITIALIZED}; |
22 | | use crate::dcerpc::dcerpc::DCERPC_TYPE_REQUEST; |
23 | | use crate::detect::uint::detect_match_uint; |
24 | | |
25 | | #[no_mangle] |
26 | 127 | pub unsafe extern "C" fn rs_smb_tx_get_share(tx: &mut SMBTransaction, |
27 | 127 | buffer: *mut *const u8, |
28 | 127 | buffer_len: *mut u32) |
29 | 127 | -> u8 |
30 | | { |
31 | 119 | if let Some(SMBTransactionTypeData::TREECONNECT(ref x)) = tx.type_data { |
32 | | SCLogDebug!("is_pipe {}", x.is_pipe); |
33 | 25 | if !x.is_pipe { |
34 | 18 | *buffer = x.share_name.as_ptr(); |
35 | 18 | *buffer_len = x.share_name.len() as u32; |
36 | 18 | return 1; |
37 | 7 | } |
38 | 102 | } |
39 | | |
40 | 109 | *buffer = ptr::null(); |
41 | 109 | *buffer_len = 0; |
42 | 109 | return 0; |
43 | 127 | } |
44 | | |
45 | | #[no_mangle] |
46 | 500 | pub unsafe extern "C" fn rs_smb_tx_get_named_pipe(tx: &mut SMBTransaction, |
47 | 500 | buffer: *mut *const u8, |
48 | 500 | buffer_len: *mut u32) |
49 | 500 | -> u8 |
50 | | { |
51 | 491 | if let Some(SMBTransactionTypeData::TREECONNECT(ref x)) = tx.type_data { |
52 | | SCLogDebug!("is_pipe {}", x.is_pipe); |
53 | 26 | if x.is_pipe { |
54 | 0 | *buffer = x.share_name.as_ptr(); |
55 | 0 | *buffer_len = x.share_name.len() as u32; |
56 | 0 | return 1; |
57 | 26 | } |
58 | 474 | } |
59 | | |
60 | 500 | *buffer = ptr::null(); |
61 | 500 | *buffer_len = 0; |
62 | 500 | return 0; |
63 | 500 | } |
64 | | |
65 | | #[no_mangle] |
66 | 165 | pub unsafe extern "C" fn rs_smb_tx_get_stub_data(tx: &mut SMBTransaction, |
67 | 165 | direction: u8, |
68 | 165 | buffer: *mut *const u8, |
69 | 165 | buffer_len: *mut u32) |
70 | 165 | -> u8 |
71 | | { |
72 | 138 | if let Some(SMBTransactionTypeData::DCERPC(ref x)) = tx.type_data { |
73 | 10 | let vref = if direction == Direction::ToServer as u8 { |
74 | 0 | &x.stub_data_ts |
75 | | } else { |
76 | 10 | &x.stub_data_tc |
77 | | }; |
78 | 10 | if !vref.is_empty() { |
79 | 3 | *buffer = vref.as_ptr(); |
80 | 3 | *buffer_len = vref.len() as u32; |
81 | 3 | return 1; |
82 | 7 | } |
83 | 155 | } |
84 | | |
85 | 162 | *buffer = ptr::null(); |
86 | 162 | *buffer_len = 0; |
87 | 162 | return 0; |
88 | 165 | } |
89 | | |
90 | | #[no_mangle] |
91 | 771 | pub extern "C" fn rs_smb_tx_match_dce_opnum(tx: &mut SMBTransaction, |
92 | 771 | dce_data: &mut DCEOpnumData) |
93 | 771 | -> u8 |
94 | | { |
95 | | SCLogDebug!("rs_smb_tx_get_dce_opnum: start"); |
96 | 729 | if let Some(SMBTransactionTypeData::DCERPC(ref x)) = tx.type_data { |
97 | 288 | if x.req_cmd == DCERPC_TYPE_REQUEST { |
98 | 260 | for range in dce_data.data.iter() { |
99 | 260 | if range.range2 == DETECT_DCE_OPNUM_RANGE_UNINITIALIZED { |
100 | 260 | if range.range1 == x.opnum as u32 { |
101 | 41 | return 1; |
102 | 219 | } |
103 | 0 | } else if range.range1 <= x.opnum as u32 && range.range2 >= x.opnum as u32 { |
104 | 0 | return 1; |
105 | 0 | } |
106 | | } |
107 | 28 | } |
108 | 483 | } |
109 | | |
110 | 730 | return 0; |
111 | 771 | } |
112 | | |
113 | | /* mimic logic that is/was in the C code: |
114 | | * - match on REQUEST (so not on BIND/BINDACK (probably for mixing with |
115 | | * dce_opnum and dce_stub_data) |
116 | | * - only match on approved ifaces (so ack_result == 0) */ |
117 | | #[no_mangle] |
118 | 1.88k | pub extern "C" fn rs_smb_tx_get_dce_iface(state: &mut SMBState, |
119 | 1.88k | tx: &mut SMBTransaction, |
120 | 1.88k | dce_data: &mut DCEIfaceData) |
121 | 1.88k | -> u8 |
122 | | { |
123 | 1.88k | let if_uuid = dce_data.if_uuid.as_slice(); |
124 | 1.88k | let is_dcerpc_request = match tx.type_data { |
125 | 529 | Some(SMBTransactionTypeData::DCERPC(ref x)) => { |
126 | 529 | x.req_cmd == DCERPC_TYPE_REQUEST |
127 | | }, |
128 | 1.35k | _ => { false }, |
129 | | }; |
130 | 1.88k | if !is_dcerpc_request { |
131 | 1.44k | return 0; |
132 | 440 | } |
133 | 440 | let ifaces = match state.dcerpc_ifaces { |
134 | 287 | Some(ref x) => x, |
135 | | _ => { |
136 | 153 | return 0; |
137 | | }, |
138 | | }; |
139 | | |
140 | | SCLogDebug!("looking for UUID {:?}", if_uuid); |
141 | | |
142 | 364 | for i in ifaces { |
143 | | SCLogDebug!("stored UUID {:?} acked {} ack_result {}", i, i.acked, i.ack_result); |
144 | | |
145 | 325 | if i.acked && i.ack_result == 0 && i.uuid == if_uuid { |
146 | 248 | if let Some(x) = &dce_data.du16 { |
147 | 0 | if detect_match_uint(x, i.ver) { |
148 | 0 | return 1; |
149 | 0 | } |
150 | | } else { |
151 | 248 | return 1; |
152 | | } |
153 | 77 | } |
154 | | } |
155 | 39 | return 0; |
156 | 1.88k | } |
157 | | |
158 | | #[no_mangle] |
159 | 243 | pub unsafe extern "C" fn rs_smb_tx_get_ntlmssp_user(tx: &mut SMBTransaction, |
160 | 243 | buffer: *mut *const u8, |
161 | 243 | buffer_len: *mut u32) |
162 | 243 | -> u8 |
163 | | { |
164 | 155 | if let Some(SMBTransactionTypeData::SESSIONSETUP(ref x)) = tx.type_data { |
165 | 30 | if let Some(ref ntlmssp) = x.ntlmssp { |
166 | 0 | *buffer = ntlmssp.user.as_ptr(); |
167 | 0 | *buffer_len = ntlmssp.user.len() as u32; |
168 | 0 | return 1; |
169 | 30 | } |
170 | 213 | } |
171 | | |
172 | 243 | *buffer = ptr::null(); |
173 | 243 | *buffer_len = 0; |
174 | 243 | return 0; |
175 | 243 | } |
176 | | |
177 | | #[no_mangle] |
178 | 301 | pub unsafe extern "C" fn rs_smb_tx_get_ntlmssp_domain(tx: &mut SMBTransaction, |
179 | 301 | buffer: *mut *const u8, |
180 | 301 | buffer_len: *mut u32) |
181 | 301 | -> u8 |
182 | | { |
183 | 193 | if let Some(SMBTransactionTypeData::SESSIONSETUP(ref x)) = tx.type_data { |
184 | 47 | if let Some(ref ntlmssp) = x.ntlmssp { |
185 | 8 | *buffer = ntlmssp.domain.as_ptr(); |
186 | 8 | *buffer_len = ntlmssp.domain.len() as u32; |
187 | 8 | return 1; |
188 | 39 | } |
189 | 254 | } |
190 | | |
191 | 293 | *buffer = ptr::null(); |
192 | 293 | *buffer_len = 0; |
193 | 293 | return 0; |
194 | 301 | } |