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