1 /* Copyright (C) 2018-2020 Open Information Security Foundation
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
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.
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
19 use crate::core::{self, ALPROTO_UNKNOWN, AppProto, Flow, IPPROTO_TCP};
20 use crate::applayer::{self, *};
21 use std::ffi::CString;
25 static mut ALPROTO_TEMPLATE: AppProto = ALPROTO_UNKNOWN;
27 pub struct TemplateTransaction {
29 pub request: Option<String>,
30 pub response: Option<String>,
32 de_state: Option<*mut core::DetectEngineState>,
33 events: *mut core::AppLayerDecoderEvents,
34 tx_data: AppLayerTxData,
37 impl TemplateTransaction {
38 pub fn new() -> TemplateTransaction {
44 events: std::ptr::null_mut(),
45 tx_data: AppLayerTxData::new(),
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);
53 if let Some(state) = self.de_state {
54 core::sc_detect_engine_state_free(state);
59 impl Drop for TemplateTransaction {
65 pub struct TemplateState {
67 transactions: Vec<TemplateTransaction>,
73 pub fn new() -> Self {
76 transactions: Vec::new(),
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;
88 let tx = &self.transactions[i];
89 if tx.tx_id == tx_id + 1 {
96 self.transactions.remove(index);
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 {
109 fn new_tx(&mut self) -> TemplateTransaction {
110 let mut tx = TemplateTransaction::new();
112 tx.tx_id = self.tx_id;
116 fn find_request(&mut self) -> Option<&mut TemplateTransaction> {
117 for tx in &mut self.transactions {
118 if tx.response.is_none() {
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();
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();
139 // It looks like we're in sync with a message header, clear gap
140 // state and keep parsing.
141 self.request_gap = false;
144 let mut start = input;
145 while start.len() > 0 {
146 match parser::parse_message(start) {
147 Ok((rem, request)) => {
150 SCLogNotice!("Request: {}", request);
151 let mut tx = self.new_tx();
152 tx.request = Some(request);
153 self.transactions.push(tx);
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);
164 return AppLayerResult::err();
169 // Input was fully consumed.
170 return AppLayerResult::ok();
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();
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();
186 // It looks like we're in sync with a message header, clear gap
187 // state and keep parsing.
188 self.response_gap = false;
190 let mut start = input;
191 while start.len() > 0 {
192 match parser::parse_message(start) {
193 Ok((rem, response)) => {
196 match self.find_request() {
198 tx.response = Some(response);
199 SCLogNotice!("Found response for request:");
200 SCLogNotice!("- Request: {:?}", tx.request);
201 SCLogNotice!("- Response: {:?}", tx.response);
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);
212 return AppLayerResult::err();
217 // All input was fully consumed.
218 return AppLayerResult::ok();
225 ) -> Option<(&TemplateTransaction, u64, bool)> {
226 let mut index = *state as usize;
227 let len = self.transactions.len();
230 let tx = &self.transactions[index];
231 if tx.tx_id < min_tx_id + 1 {
235 *state = index as u64;
236 return Some((tx, tx.tx_id - 1, (len - index) > 1));
242 fn on_request_gap(&mut self, _size: u32) {
243 self.request_gap = true;
246 fn on_response_gap(&mut self, _size: u32) {
247 self.response_gap = true;
251 /// Probe for a valid header.
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(":"),
268 export_tx_get_detect_state!(
269 rs_template_tx_get_detect_state,
272 export_tx_set_detect_state!(
273 rs_template_tx_set_detect_state,
277 /// C entry point for a probing parser.
279 pub extern "C" fn rs_template_probing_parser(
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 };
293 return ALPROTO_UNKNOWN;
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;
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) });
309 pub extern "C" fn rs_template_state_tx_free(
310 state: *mut std::os::raw::c_void,
313 let state = cast_pointer!(state, TemplateState);
314 state.free_tx(tx_id);
318 pub extern "C" fn rs_template_parse_request(
320 state: *mut std::os::raw::c_void,
321 pstate: *mut std::os::raw::c_void,
324 _data: *const std::os::raw::c_void,
326 ) -> AppLayerResult {
328 if AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) > 0 {
336 // If needed, handle EOF, or pass it into the parser.
337 return AppLayerResult::ok();
340 let state = cast_pointer!(state, TemplateState);
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);
348 let buf = build_slice!(input, input_len as usize);
349 state.parse_request(buf)
354 pub extern "C" fn rs_template_parse_response(
356 state: *mut std::os::raw::c_void,
357 pstate: *mut std::os::raw::c_void,
360 _data: *const std::os::raw::c_void,
362 ) -> AppLayerResult {
364 if AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC) > 0 {
370 let state = cast_pointer!(state, TemplateState);
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);
378 let buf = build_slice!(input, input_len as usize);
379 state.parse_response(buf).into()
384 pub extern "C" fn rs_template_state_get_tx(
385 state: *mut std::os::raw::c_void,
387 ) -> *mut std::os::raw::c_void {
388 let state = cast_pointer!(state, TemplateState);
389 match state.get_tx(tx_id) {
391 return tx as *const _ as *mut _;
394 return std::ptr::null_mut();
400 pub extern "C" fn rs_template_state_get_tx_count(
401 state: *mut std::os::raw::c_void,
403 let state = cast_pointer!(state, TemplateState);
408 pub extern "C" fn rs_template_tx_get_alstate_progress(
409 tx: *mut std::os::raw::c_void,
411 ) -> std::os::raw::c_int {
412 let tx = cast_pointer!(tx, TemplateTransaction);
414 // Transaction is done if we have a response.
415 if tx.response.is_some() {
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);
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 {
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
446 pub extern "C" fn rs_template_state_get_tx_iterator(
449 state: *mut std::os::raw::c_void,
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(
466 return applayer::AppLayerGetTxIterTuple::not_found();
471 /// Get the request buffer for a transaction from C.
473 /// No required for parsing, but an example function for retrieving a
474 /// pointer to the request buffer from C for detection.
476 pub extern "C" fn rs_template_get_request_buffer(
477 tx: *mut std::os::raw::c_void,
482 let tx = cast_pointer!(tx, TemplateTransaction);
483 if let Some(ref request) = tx.request {
484 if request.len() > 0 {
486 *len = request.len() as u32;
487 *buf = request.as_ptr();
495 /// Get the response buffer for a transaction from C.
497 pub extern "C" fn rs_template_get_response_buffer(
498 tx: *mut std::os::raw::c_void,
503 let tx = cast_pointer!(tx, TemplateTransaction);
504 if let Some(ref response) = tx.response {
505 if response.len() > 0 {
507 *len = response.len() as u32;
508 *buf = response.as_ptr();
516 export_tx_data_get!(rs_template_get_tx_data, TemplateTransaction);
518 // Parser name as a C style string.
519 const PARSER_NAME: &'static [u8] = b"template-rust\0";
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),
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,
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,
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,
557 let ip_proto_str = CString::new("tcp").unwrap();
559 if AppLayerProtoDetectConfProtoDetectionEnabled(
560 ip_proto_str.as_ptr(),
564 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
565 ALPROTO_TEMPLATE = alproto;
566 if AppLayerParserConfParserEnabled(
567 ip_proto_str.as_ptr(),
571 let _ = AppLayerRegisterParser(&parser, alproto);
573 SCLogNotice!("Rust template parser registered.");
575 SCLogNotice!("Protocol detector and parser disabled for TEMPLATE.");
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());
592 fn test_incomplete() {
593 let mut state = TemplateState::new();
594 let buf = b"5:Hello3:bye";
596 let r = state.parse_request(&buf[0..0]);
597 assert_eq!(r, AppLayerResult{ status: 0, consumed: 0, needed: 0});
599 let r = state.parse_request(&buf[0..1]);
600 assert_eq!(r, AppLayerResult{ status: 1, consumed: 0, needed: 2});
602 let r = state.parse_request(&buf[0..2]);
603 assert_eq!(r, AppLayerResult{ status: 1, consumed: 0, needed: 3});
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});
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});