]> git.ipfire.org Git - people/ms/suricata.git/blob - rust/src/applayertemplate/template.rs
rust: remove all usage of transmute
[people/ms/suricata.git] / rust / src / applayertemplate / template.rs
1 /* Copyright (C) 2018-2020 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;
19 use crate::core::{self, ALPROTO_UNKNOWN, AppProto, Flow, IPPROTO_TCP};
20 use crate::applayer::{self, *};
21 use std::ffi::CString;
22 use nom;
23 use super::parser;
24
25 static mut ALPROTO_TEMPLATE: AppProto = ALPROTO_UNKNOWN;
26
27 pub struct TemplateTransaction {
28 tx_id: u64,
29 pub request: Option<String>,
30 pub response: Option<String>,
31
32 de_state: Option<*mut core::DetectEngineState>,
33 events: *mut core::AppLayerDecoderEvents,
34 tx_data: AppLayerTxData,
35 }
36
37 impl TemplateTransaction {
38 pub fn new() -> TemplateTransaction {
39 TemplateTransaction {
40 tx_id: 0,
41 request: None,
42 response: None,
43 de_state: None,
44 events: std::ptr::null_mut(),
45 tx_data: AppLayerTxData::new(),
46 }
47 }
48
49 pub fn free(&mut self) {
50 if self.events != std::ptr::null_mut() {
51 core::sc_app_layer_decoder_events_free_events(&mut self.events);
52 }
53 if let Some(state) = self.de_state {
54 core::sc_detect_engine_state_free(state);
55 }
56 }
57 }
58
59 impl Drop for TemplateTransaction {
60 fn drop(&mut self) {
61 self.free();
62 }
63 }
64
65 pub struct TemplateState {
66 tx_id: u64,
67 transactions: Vec<TemplateTransaction>,
68 request_gap: bool,
69 response_gap: bool,
70 }
71
72 impl TemplateState {
73 pub fn new() -> Self {
74 Self {
75 tx_id: 0,
76 transactions: Vec::new(),
77 request_gap: false,
78 response_gap: false,
79 }
80 }
81
82 // Free a transaction by ID.
83 fn free_tx(&mut self, tx_id: u64) {
84 let len = self.transactions.len();
85 let mut found = false;
86 let mut index = 0;
87 for i in 0..len {
88 let tx = &self.transactions[i];
89 if tx.tx_id == tx_id + 1 {
90 found = true;
91 index = i;
92 break;
93 }
94 }
95 if found {
96 self.transactions.remove(index);
97 }
98 }
99
100 pub fn get_tx(&mut self, tx_id: u64) -> Option<&TemplateTransaction> {
101 for tx in &mut self.transactions {
102 if tx.tx_id == tx_id + 1 {
103 return Some(tx);
104 }
105 }
106 return None;
107 }
108
109 fn new_tx(&mut self) -> TemplateTransaction {
110 let mut tx = TemplateTransaction::new();
111 self.tx_id += 1;
112 tx.tx_id = self.tx_id;
113 return tx;
114 }
115
116 fn find_request(&mut self) -> Option<&mut TemplateTransaction> {
117 for tx in &mut self.transactions {
118 if tx.response.is_none() {
119 return Some(tx);
120 }
121 }
122 None
123 }
124
125 fn parse_request(&mut self, input: &[u8]) -> AppLayerResult {
126 // We're not interested in empty requests.
127 if input.len() == 0 {
128 return AppLayerResult::ok();
129 }
130
131 // If there was gap, check we can sync up again.
132 if self.request_gap {
133 if probe(input).is_err() {
134 // The parser now needs to decide what to do as we are not in sync.
135 // For this template, we'll just try again next time.
136 return AppLayerResult::ok();
137 }
138
139 // It looks like we're in sync with a message header, clear gap
140 // state and keep parsing.
141 self.request_gap = false;
142 }
143
144 let mut start = input;
145 while start.len() > 0 {
146 match parser::parse_message(start) {
147 Ok((rem, request)) => {
148 start = rem;
149
150 SCLogNotice!("Request: {}", request);
151 let mut tx = self.new_tx();
152 tx.request = Some(request);
153 self.transactions.push(tx);
154 },
155 Err(nom::Err::Incomplete(_)) => {
156 // Not enough data. This parser doesn't give us a good indication
157 // of how much data is missing so just ask for one more byte so the
158 // parse is called as soon as more data is received.
159 let consumed = input.len() - start.len();
160 let needed = start.len() + 1;
161 return AppLayerResult::incomplete(consumed as u32, needed as u32);
162 },
163 Err(_) => {
164 return AppLayerResult::err();
165 },
166 }
167 }
168
169 // Input was fully consumed.
170 return AppLayerResult::ok();
171 }
172
173 fn parse_response(&mut self, input: &[u8]) -> AppLayerResult {
174 // We're not interested in empty responses.
175 if input.len() == 0 {
176 return AppLayerResult::ok();
177 }
178
179 if self.response_gap {
180 if probe(input).is_err() {
181 // The parser now needs to decide what to do as we are not in sync.
182 // For this template, we'll just try again next time.
183 return AppLayerResult::ok();
184 }
185
186 // It looks like we're in sync with a message header, clear gap
187 // state and keep parsing.
188 self.response_gap = false;
189 }
190 let mut start = input;
191 while start.len() > 0 {
192 match parser::parse_message(start) {
193 Ok((rem, response)) => {
194 start = rem;
195
196 match self.find_request() {
197 Some(tx) => {
198 tx.response = Some(response);
199 SCLogNotice!("Found response for request:");
200 SCLogNotice!("- Request: {:?}", tx.request);
201 SCLogNotice!("- Response: {:?}", tx.response);
202 }
203 None => {}
204 }
205 }
206 Err(nom::Err::Incomplete(_)) => {
207 let consumed = input.len() - start.len();
208 let needed = start.len() + 1;
209 return AppLayerResult::incomplete(consumed as u32, needed as u32);
210 }
211 Err(_) => {
212 return AppLayerResult::err();
213 }
214 }
215 }
216
217 // All input was fully consumed.
218 return AppLayerResult::ok();
219 }
220
221 fn tx_iterator(
222 &mut self,
223 min_tx_id: u64,
224 state: &mut u64,
225 ) -> Option<(&TemplateTransaction, u64, bool)> {
226 let mut index = *state as usize;
227 let len = self.transactions.len();
228
229 while index < len {
230 let tx = &self.transactions[index];
231 if tx.tx_id < min_tx_id + 1 {
232 index += 1;
233 continue;
234 }
235 *state = index as u64;
236 return Some((tx, tx.tx_id - 1, (len - index) > 1));
237 }
238
239 return None;
240 }
241
242 fn on_request_gap(&mut self, _size: u32) {
243 self.request_gap = true;
244 }
245
246 fn on_response_gap(&mut self, _size: u32) {
247 self.response_gap = true;
248 }
249 }
250
251 /// Probe for a valid header.
252 ///
253 /// As this template protocol uses messages prefixed with the size
254 /// as a string followed by a ':', we look at up to the first 10
255 /// characters for that pattern.
256 fn probe(input: &[u8]) -> nom::IResult<&[u8], ()> {
257 let size = std::cmp::min(10, input.len());
258 let (rem, prefix) = nom::bytes::complete::take(size)(input)?;
259 nom::sequence::terminated(
260 nom::bytes::complete::take_while1(nom::character::is_digit),
261 nom::bytes::complete::tag(":"),
262 )(prefix)?;
263 Ok((rem, ()))
264 }
265
266 // C exports.
267
268 export_tx_get_detect_state!(
269 rs_template_tx_get_detect_state,
270 TemplateTransaction
271 );
272 export_tx_set_detect_state!(
273 rs_template_tx_set_detect_state,
274 TemplateTransaction
275 );
276
277 /// C entry point for a probing parser.
278 #[no_mangle]
279 pub extern "C" fn rs_template_probing_parser(
280 _flow: *const Flow,
281 _direction: u8,
282 input: *const u8,
283 input_len: u32,
284 _rdir: *mut u8
285 ) -> AppProto {
286 // Need at least 2 bytes.
287 if input_len > 1 && input != std::ptr::null_mut() {
288 let slice = build_slice!(input, input_len as usize);
289 if probe(slice).is_ok() {
290 return unsafe { ALPROTO_TEMPLATE };
291 }
292 }
293 return ALPROTO_UNKNOWN;
294 }
295
296 #[no_mangle]
297 pub extern "C" fn rs_template_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
298 let state = TemplateState::new();
299 let boxed = Box::new(state);
300 return Box::into_raw(boxed) as *mut std::os::raw::c_void;
301 }
302
303 #[no_mangle]
304 pub extern "C" fn rs_template_state_free(state: *mut std::os::raw::c_void) {
305 std::mem::drop(unsafe { Box::from_raw(state as *mut TemplateState) });
306 }
307
308 #[no_mangle]
309 pub extern "C" fn rs_template_state_tx_free(
310 state: *mut std::os::raw::c_void,
311 tx_id: u64,
312 ) {
313 let state = cast_pointer!(state, TemplateState);
314 state.free_tx(tx_id);
315 }
316
317 #[no_mangle]
318 pub extern "C" fn rs_template_parse_request(
319 _flow: *const Flow,
320 state: *mut std::os::raw::c_void,
321 pstate: *mut std::os::raw::c_void,
322 input: *const u8,
323 input_len: u32,
324 _data: *const std::os::raw::c_void,
325 _flags: u8,
326 ) -> AppLayerResult {
327 let eof = unsafe {
328 if AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) > 0 {
329 true
330 } else {
331 false
332 }
333 };
334
335 if eof {
336 // If needed, handle EOF, or pass it into the parser.
337 return AppLayerResult::ok();
338 }
339
340 let state = cast_pointer!(state, TemplateState);
341
342 if input == std::ptr::null_mut() && input_len > 0 {
343 // Here we have a gap signaled by the input being null, but a greater
344 // than 0 input_len which provides the size of the gap.
345 state.on_request_gap(input_len);
346 AppLayerResult::ok()
347 } else {
348 let buf = build_slice!(input, input_len as usize);
349 state.parse_request(buf)
350 }
351 }
352
353 #[no_mangle]
354 pub extern "C" fn rs_template_parse_response(
355 _flow: *const Flow,
356 state: *mut std::os::raw::c_void,
357 pstate: *mut std::os::raw::c_void,
358 input: *const u8,
359 input_len: u32,
360 _data: *const std::os::raw::c_void,
361 _flags: u8,
362 ) -> AppLayerResult {
363 let _eof = unsafe {
364 if AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC) > 0 {
365 true
366 } else {
367 false
368 }
369 };
370 let state = cast_pointer!(state, TemplateState);
371
372 if input == std::ptr::null_mut() && input_len > 0 {
373 // Here we have a gap signaled by the input being null, but a greater
374 // than 0 input_len which provides the size of the gap.
375 state.on_response_gap(input_len);
376 AppLayerResult::ok()
377 } else {
378 let buf = build_slice!(input, input_len as usize);
379 state.parse_response(buf).into()
380 }
381 }
382
383 #[no_mangle]
384 pub extern "C" fn rs_template_state_get_tx(
385 state: *mut std::os::raw::c_void,
386 tx_id: u64,
387 ) -> *mut std::os::raw::c_void {
388 let state = cast_pointer!(state, TemplateState);
389 match state.get_tx(tx_id) {
390 Some(tx) => {
391 return tx as *const _ as *mut _;
392 }
393 None => {
394 return std::ptr::null_mut();
395 }
396 }
397 }
398
399 #[no_mangle]
400 pub extern "C" fn rs_template_state_get_tx_count(
401 state: *mut std::os::raw::c_void,
402 ) -> u64 {
403 let state = cast_pointer!(state, TemplateState);
404 return state.tx_id;
405 }
406
407 #[no_mangle]
408 pub extern "C" fn rs_template_tx_get_alstate_progress(
409 tx: *mut std::os::raw::c_void,
410 _direction: u8,
411 ) -> std::os::raw::c_int {
412 let tx = cast_pointer!(tx, TemplateTransaction);
413
414 // Transaction is done if we have a response.
415 if tx.response.is_some() {
416 return 1;
417 }
418 return 0;
419 }
420
421 #[no_mangle]
422 pub extern "C" fn rs_template_state_get_events(
423 tx: *mut std::os::raw::c_void
424 ) -> *mut core::AppLayerDecoderEvents {
425 let tx = cast_pointer!(tx, TemplateTransaction);
426 return tx.events;
427 }
428
429 #[no_mangle]
430 pub extern "C" fn rs_template_state_get_event_info(
431 _event_name: *const std::os::raw::c_char,
432 _event_id: *mut std::os::raw::c_int,
433 _event_type: *mut core::AppLayerEventType,
434 ) -> std::os::raw::c_int {
435 return -1;
436 }
437
438 #[no_mangle]
439 pub extern "C" fn rs_template_state_get_event_info_by_id(_event_id: std::os::raw::c_int,
440 _event_name: *mut *const std::os::raw::c_char,
441 _event_type: *mut core::AppLayerEventType
442 ) -> i8 {
443 return -1;
444 }
445 #[no_mangle]
446 pub extern "C" fn rs_template_state_get_tx_iterator(
447 _ipproto: u8,
448 _alproto: AppProto,
449 state: *mut std::os::raw::c_void,
450 min_tx_id: u64,
451 _max_tx_id: u64,
452 istate: &mut u64,
453 ) -> applayer::AppLayerGetTxIterTuple {
454 let state = cast_pointer!(state, TemplateState);
455 match state.tx_iterator(min_tx_id, istate) {
456 Some((tx, out_tx_id, has_next)) => {
457 let c_tx = tx as *const _ as *mut _;
458 let ires = applayer::AppLayerGetTxIterTuple::with_values(
459 c_tx,
460 out_tx_id,
461 has_next,
462 );
463 return ires;
464 }
465 None => {
466 return applayer::AppLayerGetTxIterTuple::not_found();
467 }
468 }
469 }
470
471 /// Get the request buffer for a transaction from C.
472 ///
473 /// No required for parsing, but an example function for retrieving a
474 /// pointer to the request buffer from C for detection.
475 #[no_mangle]
476 pub extern "C" fn rs_template_get_request_buffer(
477 tx: *mut std::os::raw::c_void,
478 buf: *mut *const u8,
479 len: *mut u32,
480 ) -> u8
481 {
482 let tx = cast_pointer!(tx, TemplateTransaction);
483 if let Some(ref request) = tx.request {
484 if request.len() > 0 {
485 unsafe {
486 *len = request.len() as u32;
487 *buf = request.as_ptr();
488 }
489 return 1;
490 }
491 }
492 return 0;
493 }
494
495 /// Get the response buffer for a transaction from C.
496 #[no_mangle]
497 pub extern "C" fn rs_template_get_response_buffer(
498 tx: *mut std::os::raw::c_void,
499 buf: *mut *const u8,
500 len: *mut u32,
501 ) -> u8
502 {
503 let tx = cast_pointer!(tx, TemplateTransaction);
504 if let Some(ref response) = tx.response {
505 if response.len() > 0 {
506 unsafe {
507 *len = response.len() as u32;
508 *buf = response.as_ptr();
509 }
510 return 1;
511 }
512 }
513 return 0;
514 }
515
516 export_tx_data_get!(rs_template_get_tx_data, TemplateTransaction);
517
518 // Parser name as a C style string.
519 const PARSER_NAME: &'static [u8] = b"template-rust\0";
520
521 #[no_mangle]
522 pub unsafe extern "C" fn rs_template_register_parser() {
523 let default_port = CString::new("[7000]").unwrap();
524 let parser = RustParser {
525 name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
526 default_port: default_port.as_ptr(),
527 ipproto: IPPROTO_TCP,
528 probe_ts: Some(rs_template_probing_parser),
529 probe_tc: Some(rs_template_probing_parser),
530 min_depth: 0,
531 max_depth: 16,
532 state_new: rs_template_state_new,
533 state_free: rs_template_state_free,
534 tx_free: rs_template_state_tx_free,
535 parse_ts: rs_template_parse_request,
536 parse_tc: rs_template_parse_response,
537 get_tx_count: rs_template_state_get_tx_count,
538 get_tx: rs_template_state_get_tx,
539 tx_comp_st_ts: 1,
540 tx_comp_st_tc: 1,
541 tx_get_progress: rs_template_tx_get_alstate_progress,
542 get_de_state: rs_template_tx_get_detect_state,
543 set_de_state: rs_template_tx_set_detect_state,
544 get_events: Some(rs_template_state_get_events),
545 get_eventinfo: Some(rs_template_state_get_event_info),
546 get_eventinfo_byid : Some(rs_template_state_get_event_info_by_id),
547 localstorage_new: None,
548 localstorage_free: None,
549 get_files: None,
550 get_tx_iterator: Some(rs_template_state_get_tx_iterator),
551 get_tx_data: rs_template_get_tx_data,
552 apply_tx_config: None,
553 flags: APP_LAYER_PARSER_OPT_ACCEPT_GAPS,
554 truncate: None,
555 };
556
557 let ip_proto_str = CString::new("tcp").unwrap();
558
559 if AppLayerProtoDetectConfProtoDetectionEnabled(
560 ip_proto_str.as_ptr(),
561 parser.name,
562 ) != 0
563 {
564 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
565 ALPROTO_TEMPLATE = alproto;
566 if AppLayerParserConfParserEnabled(
567 ip_proto_str.as_ptr(),
568 parser.name,
569 ) != 0
570 {
571 let _ = AppLayerRegisterParser(&parser, alproto);
572 }
573 SCLogNotice!("Rust template parser registered.");
574 } else {
575 SCLogNotice!("Protocol detector and parser disabled for TEMPLATE.");
576 }
577 }
578
579 #[cfg(test)]
580 mod test {
581 use super::*;
582
583 #[test]
584 fn test_probe() {
585 assert!(probe(b"1").is_err());
586 assert!(probe(b"1:").is_ok());
587 assert!(probe(b"123456789:").is_ok());
588 assert!(probe(b"0123456789:").is_err());
589 }
590
591 #[test]
592 fn test_incomplete() {
593 let mut state = TemplateState::new();
594 let buf = b"5:Hello3:bye";
595
596 let r = state.parse_request(&buf[0..0]);
597 assert_eq!(r, AppLayerResult{ status: 0, consumed: 0, needed: 0});
598
599 let r = state.parse_request(&buf[0..1]);
600 assert_eq!(r, AppLayerResult{ status: 1, consumed: 0, needed: 2});
601
602 let r = state.parse_request(&buf[0..2]);
603 assert_eq!(r, AppLayerResult{ status: 1, consumed: 0, needed: 3});
604
605 // This is the first message and only the first message.
606 let r = state.parse_request(&buf[0..7]);
607 assert_eq!(r, AppLayerResult{ status: 0, consumed: 0, needed: 0});
608
609 // The first message and a portion of the second.
610 let r = state.parse_request(&buf[0..9]);
611 assert_eq!(r, AppLayerResult{ status: 1, consumed: 7, needed: 3});
612 }
613 }