]>
Commit | Line | Data |
---|---|---|
2f5834cd | 1 | /* Copyright (C) 2017-2020 Open Information Security Foundation |
c54fc7f9 JI |
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 | ||
2f5834cd VJ |
18 | //! Parser registration functions and common interface |
19 | ||
e96d9c11 | 20 | use std; |
2f5834cd VJ |
21 | use crate::core::{DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto}; |
22 | use crate::filecontainer::FileContainer; | |
23 | use crate::applayer; | |
24 | use std::os::raw::{c_void,c_char,c_int}; | |
3ada5e14 | 25 | use crate::core::SC; |
2f5834cd | 26 | |
411f428a | 27 | #[repr(C)] |
f502f21f | 28 | #[derive(Default, Debug,PartialEq)] |
411f428a VJ |
29 | pub struct AppLayerTxConfig { |
30 | /// config: log flags | |
31 | log_flags: u8, | |
32 | } | |
33 | ||
34 | impl AppLayerTxConfig { | |
35 | pub fn new() -> Self { | |
36 | Self { | |
37 | log_flags: 0, | |
38 | } | |
39 | } | |
40 | ||
41 | pub fn add_log_flags(&mut self, flags: u8) { | |
42 | self.log_flags |= flags; | |
43 | } | |
44 | pub fn set_log_flags(&mut self, flags: u8) { | |
45 | self.log_flags = flags; | |
46 | } | |
47 | pub fn get_log_flags(&self) -> u8 { | |
48 | self.log_flags | |
49 | } | |
50 | } | |
51 | ||
52 | #[repr(C)] | |
f502f21f | 53 | #[derive(Default, Debug,PartialEq)] |
411f428a VJ |
54 | pub struct AppLayerTxData { |
55 | /// config: log flags | |
56 | pub config: AppLayerTxConfig, | |
c797c9f0 VJ |
57 | |
58 | /// logger flags for tx logging api | |
59 | logged: LoggerFlags, | |
e15995e2 VJ |
60 | |
61 | /// detection engine flags for use by detection engine | |
62 | detect_flags_ts: u64, | |
63 | detect_flags_tc: u64, | |
411f428a VJ |
64 | } |
65 | ||
66 | impl AppLayerTxData { | |
67 | pub fn new() -> Self { | |
68 | Self { | |
69 | config: AppLayerTxConfig::new(), | |
c797c9f0 | 70 | logged: LoggerFlags::new(), |
e15995e2 VJ |
71 | detect_flags_ts: 0, |
72 | detect_flags_tc: 0, | |
411f428a VJ |
73 | } |
74 | } | |
75 | } | |
76 | ||
77 | #[macro_export] | |
78 | macro_rules!export_tx_data_get { | |
79 | ($name:ident, $type:ty) => { | |
80 | #[no_mangle] | |
81 | pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void) | |
82 | -> *mut crate::applayer::AppLayerTxData | |
83 | { | |
84 | let tx = &mut *(tx as *mut $type); | |
85 | &mut tx.tx_data | |
86 | } | |
87 | } | |
88 | } | |
89 | ||
2f5834cd | 90 | #[repr(C)] |
aa8871a5 | 91 | #[derive(Default,Debug,PartialEq,Copy,Clone)] |
2f5834cd VJ |
92 | pub struct AppLayerResult { |
93 | pub status: i32, | |
94 | pub consumed: u32, | |
95 | pub needed: u32, | |
96 | } | |
97 | ||
98 | impl AppLayerResult { | |
99 | /// parser has successfully processed in the input, and has consumed all of it | |
aa8871a5 JL |
100 | pub fn ok() -> Self { |
101 | Default::default() | |
2f5834cd VJ |
102 | } |
103 | /// parser has hit an unrecoverable error. Returning this to the API | |
104 | /// leads to no further calls to the parser. | |
aa8871a5 JL |
105 | pub fn err() -> Self { |
106 | return Self { | |
2f5834cd | 107 | status: -1, |
aa8871a5 | 108 | ..Default::default() |
2f5834cd VJ |
109 | }; |
110 | } | |
111 | /// parser needs more data. Through 'consumed' it will indicate how many | |
112 | /// of the input bytes it has consumed. Through 'needed' it will indicate | |
113 | /// how many more bytes it needs before getting called again. | |
114 | /// Note: consumed should never be more than the input len | |
115 | /// needed + consumed should be more than the input len | |
aa8871a5 JL |
116 | pub fn incomplete(consumed: u32, needed: u32) -> Self { |
117 | return Self { | |
2f5834cd VJ |
118 | status: 1, |
119 | consumed: consumed, | |
120 | needed: needed, | |
121 | }; | |
122 | } | |
b0288da6 VJ |
123 | |
124 | pub fn is_ok(self) -> bool { | |
125 | self.status == 0 | |
126 | } | |
127 | pub fn is_incomplete(self) -> bool { | |
128 | self.status == 1 | |
129 | } | |
130 | pub fn is_err(self) -> bool { | |
131 | self.status == -1 | |
132 | } | |
2f5834cd VJ |
133 | } |
134 | ||
acef21b7 VJ |
135 | impl From<bool> for AppLayerResult { |
136 | fn from(v: bool) -> Self { | |
137 | if v == false { | |
138 | Self::err() | |
139 | } else { | |
140 | Self::ok() | |
141 | } | |
142 | } | |
143 | } | |
144 | ||
145 | impl From<i32> for AppLayerResult { | |
146 | fn from(v: i32) -> Self { | |
147 | if v < 0 { | |
148 | Self::err() | |
149 | } else { | |
150 | Self::ok() | |
151 | } | |
152 | } | |
153 | } | |
154 | ||
2f5834cd VJ |
155 | /// Rust parser declaration |
156 | #[repr(C)] | |
157 | pub struct RustParser { | |
158 | /// Parser name. | |
159 | pub name: *const c_char, | |
160 | /// Default port | |
161 | pub default_port: *const c_char, | |
162 | ||
163 | /// IP Protocol (core::IPPROTO_UDP, core::IPPROTO_TCP, etc.) | |
164 | pub ipproto: c_int, | |
165 | ||
166 | /// Probing function, for packets going to server | |
167 | pub probe_ts: Option<ProbeFn>, | |
168 | /// Probing function, for packets going to client | |
169 | pub probe_tc: Option<ProbeFn>, | |
170 | ||
171 | /// Minimum frame depth for probing | |
172 | pub min_depth: u16, | |
173 | /// Maximum frame depth for probing | |
174 | pub max_depth: u16, | |
175 | ||
176 | /// Allocation function for a new state | |
177 | pub state_new: StateAllocFn, | |
178 | /// Function called to free a state | |
179 | pub state_free: StateFreeFn, | |
180 | ||
181 | /// Parsing function, for packets going to server | |
182 | pub parse_ts: ParseFn, | |
183 | /// Parsing function, for packets going to client | |
184 | pub parse_tc: ParseFn, | |
185 | ||
186 | /// Get the current transaction count | |
187 | pub get_tx_count: StateGetTxCntFn, | |
188 | /// Get a transaction | |
189 | pub get_tx: StateGetTxFn, | |
190 | /// Function called to free a transaction | |
191 | pub tx_free: StateTxFreeFn, | |
efc9a7a3 VJ |
192 | /// Progress values at which the tx is considered complete in a direction |
193 | pub tx_comp_st_ts: c_int, | |
194 | pub tx_comp_st_tc: c_int, | |
2f5834cd VJ |
195 | /// Function returning the current transaction progress |
196 | pub tx_get_progress: StateGetProgressFn, | |
197 | ||
2f5834cd VJ |
198 | /// Function called to get a detection state |
199 | pub get_de_state: GetDetectStateFn, | |
200 | /// Function called to set a detection state | |
201 | pub set_de_state: SetDetectStateFn, | |
202 | ||
203 | /// Function to get events | |
204 | pub get_events: Option<GetEventsFn>, | |
205 | /// Function to get an event id from a description | |
206 | pub get_eventinfo: Option<GetEventInfoFn>, | |
207 | /// Function to get an event description from an event id | |
208 | pub get_eventinfo_byid: Option<GetEventInfoByIdFn>, | |
209 | ||
210 | /// Function to allocate local storage | |
211 | pub localstorage_new: Option<LocalStorageNewFn>, | |
212 | /// Function to free local storage | |
213 | pub localstorage_free: Option<LocalStorageFreeFn>, | |
214 | ||
2f5834cd VJ |
215 | /// Function to get files |
216 | pub get_files: Option<GetFilesFn>, | |
217 | ||
218 | /// Function to get the TX iterator | |
219 | pub get_tx_iterator: Option<GetTxIteratorFn>, | |
220 | ||
c94a5e63 | 221 | pub get_tx_data: GetTxDataFn, |
5665fc83 VJ |
222 | |
223 | // Function to apply config to a TX. Optional. Normal (bidirectional) | |
224 | // transactions don't need to set this. It is meant for cases where | |
225 | // the requests and responses are not sharing tx. It is then up to | |
226 | // the implementation to make sure the config is applied correctly. | |
227 | pub apply_tx_config: Option<ApplyTxConfigFn>, | |
53aa967e JI |
228 | |
229 | pub flags: u32, | |
4da0d9bd VJ |
230 | |
231 | /// Function to handle the end of data coming on one of the sides | |
232 | /// due to the stream reaching its 'depth' limit. | |
233 | pub truncate: Option<TruncateFn>, | |
2f5834cd VJ |
234 | } |
235 | ||
236 | /// Create a slice, given a buffer and a length | |
237 | /// | |
238 | /// UNSAFE ! | |
239 | #[macro_export] | |
240 | macro_rules! build_slice { | |
363b5f99 | 241 | ($buf:ident, $len:expr) => ( std::slice::from_raw_parts($buf, $len) ); |
2f5834cd VJ |
242 | } |
243 | ||
244 | /// Cast pointer to a variable, as a mutable reference to an object | |
245 | /// | |
246 | /// UNSAFE ! | |
247 | #[macro_export] | |
248 | macro_rules! cast_pointer { | |
363b5f99 | 249 | ($ptr:ident, $ty:ty) => ( &mut *($ptr as *mut $ty) ); |
2f5834cd VJ |
250 | } |
251 | ||
363b5f99 | 252 | pub type ParseFn = unsafe extern "C" fn (flow: *const Flow, |
2f5834cd VJ |
253 | state: *mut c_void, |
254 | pstate: *mut c_void, | |
255 | input: *const u8, | |
256 | input_len: u32, | |
257 | data: *const c_void, | |
258 | flags: u8) -> AppLayerResult; | |
363b5f99 | 259 | pub type ProbeFn = unsafe extern "C" fn (flow: *const Flow, flags: u8, input:*const u8, input_len: u32, rdir: *mut u8) -> AppProto; |
547d6c2d | 260 | pub type StateAllocFn = extern "C" fn (*mut c_void, AppProto) -> *mut c_void; |
363b5f99 JI |
261 | pub type StateFreeFn = unsafe extern "C" fn (*mut c_void); |
262 | pub type StateTxFreeFn = unsafe extern "C" fn (*mut c_void, u64); | |
263 | pub type StateGetTxFn = unsafe extern "C" fn (*mut c_void, u64) -> *mut c_void; | |
264 | pub type StateGetTxCntFn = unsafe extern "C" fn (*mut c_void) -> u64; | |
265 | pub type StateGetProgressFn = unsafe extern "C" fn (*mut c_void, u8) -> c_int; | |
266 | pub type GetDetectStateFn = unsafe extern "C" fn (*mut c_void) -> *mut DetectEngineState; | |
267 | pub type SetDetectStateFn = unsafe extern "C" fn (*mut c_void, &mut DetectEngineState) -> c_int; | |
268 | pub type GetEventInfoFn = unsafe extern "C" fn (*const c_char, *mut c_int, *mut AppLayerEventType) -> c_int; | |
269 | pub type GetEventInfoByIdFn = unsafe extern "C" fn (c_int, *mut *const c_char, *mut AppLayerEventType) -> i8; | |
270 | pub type GetEventsFn = unsafe extern "C" fn (*mut c_void) -> *mut AppLayerDecoderEvents; | |
2f5834cd VJ |
271 | pub type LocalStorageNewFn = extern "C" fn () -> *mut c_void; |
272 | pub type LocalStorageFreeFn = extern "C" fn (*mut c_void); | |
363b5f99 JI |
273 | pub type GetFilesFn = unsafe |
274 | extern "C" fn (*mut c_void, u8) -> *mut FileContainer; | |
275 | pub type GetTxIteratorFn = unsafe extern "C" fn (ipproto: u8, alproto: AppProto, | |
2f5834cd VJ |
276 | state: *mut c_void, |
277 | min_tx_id: u64, | |
278 | max_tx_id: u64, | |
279 | istate: &mut u64) | |
280 | -> AppLayerGetTxIterTuple; | |
411f428a | 281 | pub type GetTxDataFn = unsafe extern "C" fn(*mut c_void) -> *mut AppLayerTxData; |
5665fc83 | 282 | pub type ApplyTxConfigFn = unsafe extern "C" fn (*mut c_void, *mut c_void, c_int, AppLayerTxConfig); |
4da0d9bd VJ |
283 | pub type TruncateFn = unsafe extern "C" fn (*mut c_void, u8); |
284 | ||
2f5834cd VJ |
285 | |
286 | // Defined in app-layer-register.h | |
287 | extern { | |
288 | pub fn AppLayerRegisterProtocolDetection(parser: *const RustParser, enable_default: c_int) -> AppProto; | |
ab6171c4 | 289 | pub fn AppLayerRegisterParserAlias(parser_name: *const c_char, alias_name: *const c_char); |
3ada5e14 JI |
290 | } |
291 | ||
292 | #[allow(non_snake_case)] | |
293 | pub unsafe fn AppLayerRegisterParser(parser: *const RustParser, alproto: AppProto) -> c_int { | |
294 | (SC.unwrap().AppLayerRegisterParser)(parser, alproto) | |
2f5834cd VJ |
295 | } |
296 | ||
297 | // Defined in app-layer-detect-proto.h | |
298 | extern { | |
cb8bd8c6 SB |
299 | pub fn AppLayerProtoDetectPPRegister(ipproto: u8, portstr: *const c_char, alproto: AppProto, |
300 | min_depth: u16, max_depth: u16, dir: u8, | |
301 | pparser1: ProbeFn, pparser2: ProbeFn); | |
302 | pub fn AppLayerProtoDetectPPParseConfPorts(ipproto_name: *const c_char, ipproto: u8, | |
303 | alproto_name: *const c_char, alproto: AppProto, | |
304 | min_depth: u16, max_depth: u16, | |
305 | pparser_ts: ProbeFn, pparser_tc: ProbeFn) -> i32; | |
306 | pub fn AppLayerProtoDetectPMRegisterPatternCSwPP(ipproto: u8, alproto: AppProto, | |
d66ad96f SB |
307 | pattern: *const c_char, depth: u16, |
308 | offset: u16, direction: u8, ppfn: ProbeFn, | |
309 | pp_min_depth: u16, pp_max_depth: u16) -> c_int; | |
2f5834cd VJ |
310 | pub fn AppLayerProtoDetectConfProtoDetectionEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int; |
311 | } | |
312 | ||
313 | // Defined in app-layer-parser.h | |
fdab22d9 PA |
314 | pub const APP_LAYER_PARSER_EOF_TS : u8 = BIT_U8!(5); |
315 | pub const APP_LAYER_PARSER_EOF_TC : u8 = BIT_U8!(6); | |
316 | pub const APP_LAYER_PARSER_NO_INSPECTION : u8 = BIT_U8!(1); | |
317 | pub const APP_LAYER_PARSER_NO_REASSEMBLY : u8 = BIT_U8!(2); | |
318 | pub const APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD : u8 = BIT_U8!(3); | |
319 | pub const APP_LAYER_PARSER_BYPASS_READY : u8 = BIT_U8!(4); | |
e96d9c11 | 320 | |
a0e3e2d7 | 321 | pub const APP_LAYER_PARSER_OPT_ACCEPT_GAPS: u32 = BIT_U32!(0); |
ac3cf6ff | 322 | pub const APP_LAYER_PARSER_OPT_UNIDIR_TXS: u32 = BIT_U32!(1); |
a0e3e2d7 | 323 | |
363b5f99 | 324 | pub type AppLayerGetTxIteratorFn = unsafe extern "C" fn (ipproto: u8, |
2f5834cd VJ |
325 | alproto: AppProto, |
326 | alstate: *mut c_void, | |
327 | min_tx_id: u64, | |
328 | max_tx_id: u64, | |
329 | istate: &mut u64) -> applayer::AppLayerGetTxIterTuple; | |
330 | ||
331 | extern { | |
332 | pub fn AppLayerParserStateSetFlag(state: *mut c_void, flag: u8); | |
333 | pub fn AppLayerParserStateIssetFlag(state: *mut c_void, flag: u8) -> c_int; | |
cb8bd8c6 | 334 | pub fn AppLayerParserSetStreamDepth(ipproto: u8, alproto: AppProto, stream_depth: u32); |
2f5834cd VJ |
335 | pub fn AppLayerParserConfParserEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int; |
336 | pub fn AppLayerParserRegisterGetTxIterator(ipproto: u8, alproto: AppProto, fun: AppLayerGetTxIteratorFn); | |
2f5834cd VJ |
337 | pub fn AppLayerParserRegisterOptionFlags(ipproto: u8, alproto: AppProto, flags: u32); |
338 | } | |
339 | ||
e96d9c11 VJ |
340 | #[repr(C)] |
341 | pub struct AppLayerGetTxIterTuple { | |
3f6624bf | 342 | tx_ptr: *mut std::os::raw::c_void, |
e96d9c11 VJ |
343 | tx_id: u64, |
344 | has_next: bool, | |
345 | } | |
346 | ||
347 | impl AppLayerGetTxIterTuple { | |
3f6624bf | 348 | pub fn with_values(tx_ptr: *mut std::os::raw::c_void, tx_id: u64, has_next: bool) -> AppLayerGetTxIterTuple { |
e96d9c11 VJ |
349 | AppLayerGetTxIterTuple { |
350 | tx_ptr: tx_ptr, tx_id: tx_id, has_next: has_next, | |
351 | } | |
352 | } | |
353 | pub fn not_found() -> AppLayerGetTxIterTuple { | |
354 | AppLayerGetTxIterTuple { | |
355 | tx_ptr: std::ptr::null_mut(), tx_id: 0, has_next: false, | |
356 | } | |
357 | } | |
358 | } | |
359 | ||
c54fc7f9 | 360 | /// LoggerFlags tracks which loggers have already been executed. |
c797c9f0 | 361 | #[repr(C)] |
f502f21f | 362 | #[derive(Default, Debug,PartialEq)] |
c54fc7f9 JI |
363 | pub struct LoggerFlags { |
364 | flags: u32, | |
365 | } | |
366 | ||
367 | impl LoggerFlags { | |
368 | ||
aa8871a5 JL |
369 | pub fn new() -> Self { |
370 | Default::default() | |
c54fc7f9 JI |
371 | } |
372 | ||
bca0cd71 VJ |
373 | pub fn get(&self) -> u32 { |
374 | self.flags | |
375 | } | |
376 | ||
377 | pub fn set(&mut self, bits: u32) { | |
378 | self.flags = bits; | |
379 | } | |
380 | ||
c54fc7f9 | 381 | } |
2ec33816 JI |
382 | |
383 | /// Export a function to get the DetectEngineState on a struct. | |
384 | #[macro_export] | |
385 | macro_rules!export_tx_get_detect_state { | |
386 | ($name:ident, $type:ty) => ( | |
387 | #[no_mangle] | |
363b5f99 | 388 | pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void) |
2ec33816 JI |
389 | -> *mut core::DetectEngineState |
390 | { | |
391 | let tx = cast_pointer!(tx, $type); | |
392 | match tx.de_state { | |
393 | Some(ds) => { | |
394 | return ds; | |
395 | }, | |
396 | None => { | |
397 | return std::ptr::null_mut(); | |
398 | } | |
399 | } | |
400 | } | |
401 | ) | |
402 | } | |
403 | ||
404 | /// Export a function to set the DetectEngineState on a struct. | |
405 | #[macro_export] | |
406 | macro_rules!export_tx_set_detect_state { | |
407 | ($name:ident, $type:ty) => ( | |
408 | #[no_mangle] | |
363b5f99 | 409 | pub unsafe extern "C" fn $name(tx: *mut std::os::raw::c_void, |
3f6624bf | 410 | de_state: &mut core::DetectEngineState) -> std::os::raw::c_int |
2ec33816 JI |
411 | { |
412 | let tx = cast_pointer!(tx, $type); | |
413 | tx.de_state = Some(de_state); | |
414 | 0 | |
415 | } | |
416 | ) | |
417 | } |