]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/sip/sip.rs
rust: functions that reference raw pointers are unsafe
[people/ms/suricata.git] / rust / src / sip / sip.rs
CommitLineData
2f5834cd 1/* Copyright (C) 2019-2020 Open Information Security Foundation
2e975a04
GL
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// written by Giuseppe Longo <giuseppe@glongo.it>
19
20extern crate nom;
21
2f5834cd 22use crate::applayer::{self, *};
e68dfa46
JI
23use crate::core;
24use crate::core::{sc_detect_engine_state_free, AppProto, Flow, ALPROTO_UNKNOWN};
e68dfa46 25use crate::sip::parser::*;
517ecd68
JI
26use std;
27use std::ffi::{CStr, CString};
2e975a04
GL
28
29#[repr(u32)]
30pub enum SIPEvent {
31 IncompleteData = 0,
32 InvalidData,
33}
34
35impl SIPEvent {
36 fn from_i32(value: i32) -> Option<SIPEvent> {
37 match value {
38 0 => Some(SIPEvent::IncompleteData),
39 1 => Some(SIPEvent::InvalidData),
40 _ => None,
41 }
42 }
43}
44
45pub struct SIPState {
46 transactions: Vec<SIPTransaction>,
47 tx_id: u64,
48}
49
50pub struct SIPTransaction {
51 id: u64,
52 pub request: Option<Request>,
53 pub response: Option<Response>,
54 pub request_line: Option<String>,
55 pub response_line: Option<String>,
56 de_state: Option<*mut core::DetectEngineState>,
57 events: *mut core::AppLayerDecoderEvents,
4ff51a0e 58 tx_data: applayer::AppLayerTxData,
2e975a04
GL
59}
60
61impl SIPState {
62 pub fn new() -> SIPState {
517ecd68 63 SIPState {
2e975a04
GL
64 transactions: Vec::new(),
65 tx_id: 0,
66 }
67 }
68
69 pub fn free(&mut self) {
70 self.transactions.clear();
71 }
72
73 fn new_tx(&mut self) -> SIPTransaction {
74 self.tx_id += 1;
75 SIPTransaction::new(self.tx_id)
76 }
77
78 fn get_tx_by_id(&mut self, tx_id: u64) -> Option<&SIPTransaction> {
79 self.transactions.iter().find(|&tx| tx.id == tx_id + 1)
80 }
81
82 fn free_tx(&mut self, tx_id: u64) {
517ecd68
JI
83 let tx = self
84 .transactions
85 .iter()
86 .position(|ref tx| tx.id == tx_id + 1);
2e975a04
GL
87 debug_assert!(tx != None);
88 if let Some(idx) = tx {
89 let _ = self.transactions.remove(idx);
90 }
91 }
92
93 fn set_event(&mut self, event: SIPEvent) {
94 if let Some(tx) = self.transactions.last_mut() {
95 let ev = event as u8;
96 core::sc_app_layer_decoder_events_set_event_raw(&mut tx.events, ev);
97 }
98 }
99
100 fn parse_request(&mut self, input: &[u8]) -> bool {
101 match sip_parse_request(input) {
102 Ok((_, request)) => {
103 let mut tx = self.new_tx();
104 tx.request = Some(request);
105 if let Ok((_, req_line)) = sip_take_line(input) {
106 tx.request_line = req_line;
107 }
108 self.transactions.push(tx);
109 return true;
110 }
111 Err(nom::Err::Incomplete(_)) => {
112 self.set_event(SIPEvent::IncompleteData);
113 return false;
114 }
115 Err(_) => {
116 self.set_event(SIPEvent::InvalidData);
117 return false;
118 }
119 }
120 }
121
122 fn parse_response(&mut self, input: &[u8]) -> bool {
123 match sip_parse_response(input) {
124 Ok((_, response)) => {
125 let mut tx = self.new_tx();
126 tx.response = Some(response);
127 if let Ok((_, resp_line)) = sip_take_line(input) {
128 tx.response_line = resp_line;
129 }
130 self.transactions.push(tx);
131 return true;
132 }
133 Err(nom::Err::Incomplete(_)) => {
134 self.set_event(SIPEvent::IncompleteData);
135 return false;
136 }
137 Err(_) => {
138 self.set_event(SIPEvent::InvalidData);
139 return false;
140 }
141 }
142 }
143}
144
145impl SIPTransaction {
146 pub fn new(id: u64) -> SIPTransaction {
517ecd68 147 SIPTransaction {
2e975a04
GL
148 id: id,
149 de_state: None,
150 request: None,
151 response: None,
152 request_line: None,
153 response_line: None,
154 events: std::ptr::null_mut(),
4ff51a0e 155 tx_data: applayer::AppLayerTxData::new(),
2e975a04
GL
156 }
157 }
158}
159
160impl Drop for SIPTransaction {
161 fn drop(&mut self) {
162 if self.events != std::ptr::null_mut() {
163 core::sc_app_layer_decoder_events_free_events(&mut self.events);
164 }
165 if let Some(state) = self.de_state {
166 sc_detect_engine_state_free(state);
167 }
168 }
169}
170
171#[no_mangle]
547d6c2d 172pub extern "C" fn rs_sip_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
2e975a04
GL
173 let state = SIPState::new();
174 let boxed = Box::new(state);
53413f2d 175 return Box::into_raw(boxed) as *mut _;
2e975a04
GL
176}
177
178#[no_mangle]
179pub extern "C" fn rs_sip_state_free(state: *mut std::os::raw::c_void) {
53413f2d 180 let mut state = unsafe { Box::from_raw(state as *mut SIPState) };
2e975a04
GL
181 state.free();
182}
183
184#[no_mangle]
363b5f99 185pub unsafe extern "C" fn rs_sip_state_get_tx(
517ecd68
JI
186 state: *mut std::os::raw::c_void,
187 tx_id: u64,
188) -> *mut std::os::raw::c_void {
189 let state = cast_pointer!(state, SIPState);
2e975a04 190 match state.get_tx_by_id(tx_id) {
53413f2d 191 Some(tx) => tx as *const _ as *mut _,
517ecd68 192 None => std::ptr::null_mut(),
2e975a04
GL
193 }
194}
195
196#[no_mangle]
363b5f99 197pub unsafe extern "C" fn rs_sip_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 {
517ecd68 198 let state = cast_pointer!(state, SIPState);
2e975a04
GL
199 state.tx_id
200}
201
202#[no_mangle]
363b5f99 203pub unsafe extern "C" fn rs_sip_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) {
517ecd68 204 let state = cast_pointer!(state, SIPState);
2e975a04
GL
205 state.free_tx(tx_id);
206}
207
2e975a04 208#[no_mangle]
517ecd68
JI
209pub extern "C" fn rs_sip_tx_get_alstate_progress(
210 _tx: *mut std::os::raw::c_void,
211 _direction: u8,
212) -> std::os::raw::c_int {
2e975a04
GL
213 1
214}
215
2e975a04 216#[no_mangle]
363b5f99 217pub unsafe extern "C" fn rs_sip_state_set_tx_detect_state(
2e975a04 218 tx: *mut std::os::raw::c_void,
517ecd68
JI
219 de_state: &mut core::DetectEngineState,
220) -> std::os::raw::c_int {
221 let tx = cast_pointer!(tx, SIPTransaction);
2e975a04
GL
222 tx.de_state = Some(de_state);
223 0
224}
225
226#[no_mangle]
363b5f99 227pub unsafe extern "C" fn rs_sip_state_get_tx_detect_state(
517ecd68
JI
228 tx: *mut std::os::raw::c_void,
229) -> *mut core::DetectEngineState {
230 let tx = cast_pointer!(tx, SIPTransaction);
2e975a04
GL
231 match tx.de_state {
232 Some(ds) => ds,
233 None => std::ptr::null_mut(),
234 }
235}
236
2e975a04 237#[no_mangle]
363b5f99 238pub unsafe extern "C" fn rs_sip_state_get_events(
517ecd68
JI
239 tx: *mut std::os::raw::c_void,
240) -> *mut core::AppLayerDecoderEvents {
2e975a04 241 let tx = cast_pointer!(tx, SIPTransaction);
517ecd68 242 return tx.events;
2e975a04
GL
243}
244
245#[no_mangle]
363b5f99 246pub unsafe extern "C" fn rs_sip_state_get_event_info(
517ecd68
JI
247 event_name: *const std::os::raw::c_char,
248 event_id: *mut std::os::raw::c_int,
249 event_type: *mut core::AppLayerEventType,
250) -> std::os::raw::c_int {
251 if event_name == std::ptr::null() {
252 return -1;
253 }
363b5f99 254 let c_event_name: &CStr = CStr::from_ptr(event_name);
2e975a04
GL
255 let event = match c_event_name.to_str() {
256 Ok(s) => {
257 match s {
517ecd68
JI
258 "incomplete_data" => SIPEvent::IncompleteData as i32,
259 "invalid_data" => SIPEvent::InvalidData as i32,
260 _ => -1, // unknown event
2e975a04 261 }
517ecd68 262 }
2e975a04
GL
263 Err(_) => -1, // UTF-8 conversion failed
264 };
363b5f99
JI
265 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
266 *event_id = event as std::os::raw::c_int;
2e975a04
GL
267 0
268}
269
270#[no_mangle]
363b5f99 271pub unsafe extern "C" fn rs_sip_state_get_event_info_by_id(
517ecd68
JI
272 event_id: std::os::raw::c_int,
273 event_name: *mut *const std::os::raw::c_char,
274 event_type: *mut core::AppLayerEventType,
275) -> i8 {
2e975a04
GL
276 if let Some(e) = SIPEvent::from_i32(event_id as i32) {
277 let estr = match e {
517ecd68
JI
278 SIPEvent::IncompleteData => "incomplete_data\0",
279 SIPEvent::InvalidData => "invalid_data\0",
2e975a04 280 };
363b5f99
JI
281 *event_name = estr.as_ptr() as *const std::os::raw::c_char;
282 *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
2e975a04
GL
283 0
284 } else {
285 -1
286 }
287}
288
517ecd68 289static mut ALPROTO_SIP: AppProto = ALPROTO_UNKNOWN;
2e975a04
GL
290
291#[no_mangle]
363b5f99 292pub unsafe extern "C" fn rs_sip_probing_parser_ts(
517ecd68
JI
293 _flow: *const Flow,
294 _direction: u8,
295 input: *const u8,
296 input_len: u32,
297 _rdir: *mut u8,
298) -> AppProto {
2e975a04
GL
299 let buf = build_slice!(input, input_len as usize);
300 if sip_parse_request(buf).is_ok() {
363b5f99 301 return ALPROTO_SIP;
2e975a04
GL
302 }
303 return ALPROTO_UNKNOWN;
304}
305
306#[no_mangle]
363b5f99 307pub unsafe extern "C" fn rs_sip_probing_parser_tc(
517ecd68
JI
308 _flow: *const Flow,
309 _direction: u8,
310 input: *const u8,
311 input_len: u32,
312 _rdir: *mut u8,
313) -> AppProto {
2e975a04
GL
314 let buf = build_slice!(input, input_len as usize);
315 if sip_parse_response(buf).is_ok() {
363b5f99 316 return ALPROTO_SIP;
2e975a04
GL
317 }
318 return ALPROTO_UNKNOWN;
319}
320
321#[no_mangle]
363b5f99 322pub unsafe extern "C" fn rs_sip_parse_request(
517ecd68
JI
323 _flow: *const core::Flow,
324 state: *mut std::os::raw::c_void,
325 _pstate: *mut std::os::raw::c_void,
326 input: *const u8,
327 input_len: u32,
328 _data: *const std::os::raw::c_void,
329 _flags: u8,
44d3f264 330) -> AppLayerResult {
517ecd68
JI
331 let buf = build_slice!(input, input_len as usize);
332 let state = cast_pointer!(state, SIPState);
acef21b7 333 state.parse_request(buf).into()
2e975a04
GL
334}
335
336#[no_mangle]
363b5f99 337pub unsafe extern "C" fn rs_sip_parse_response(
517ecd68
JI
338 _flow: *const core::Flow,
339 state: *mut std::os::raw::c_void,
340 _pstate: *mut std::os::raw::c_void,
341 input: *const u8,
342 input_len: u32,
343 _data: *const std::os::raw::c_void,
344 _flags: u8,
44d3f264 345) -> AppLayerResult {
517ecd68
JI
346 let buf = build_slice!(input, input_len as usize);
347 let state = cast_pointer!(state, SIPState);
acef21b7 348 state.parse_response(buf).into()
2e975a04
GL
349}
350
4ff51a0e
VJ
351export_tx_data_get!(rs_sip_get_tx_data, SIPTransaction);
352
517ecd68 353const PARSER_NAME: &'static [u8] = b"sip\0";
2e975a04
GL
354
355#[no_mangle]
356pub unsafe extern "C" fn rs_sip_register_parser() {
357 let default_port = CString::new("5060").unwrap();
358 let parser = RustParser {
517ecd68
JI
359 name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
360 default_port: default_port.as_ptr(),
361 ipproto: core::IPPROTO_UDP,
66632465
PA
362 probe_ts: Some(rs_sip_probing_parser_ts),
363 probe_tc: Some(rs_sip_probing_parser_tc),
517ecd68
JI
364 min_depth: 0,
365 max_depth: 16,
366 state_new: rs_sip_state_new,
367 state_free: rs_sip_state_free,
368 tx_free: rs_sip_state_tx_free,
369 parse_ts: rs_sip_parse_request,
370 parse_tc: rs_sip_parse_response,
371 get_tx_count: rs_sip_state_get_tx_count,
372 get_tx: rs_sip_state_get_tx,
efc9a7a3
VJ
373 tx_comp_st_ts: 1,
374 tx_comp_st_tc: 1,
517ecd68 375 tx_get_progress: rs_sip_tx_get_alstate_progress,
517ecd68
JI
376 get_de_state: rs_sip_state_get_tx_detect_state,
377 set_de_state: rs_sip_state_set_tx_detect_state,
378 get_events: Some(rs_sip_state_get_events),
379 get_eventinfo: Some(rs_sip_state_get_event_info),
380 get_eventinfo_byid: Some(rs_sip_state_get_event_info_by_id),
381 localstorage_new: None,
382 localstorage_free: None,
517ecd68
JI
383 get_files: None,
384 get_tx_iterator: None,
c94a5e63 385 get_tx_data: rs_sip_get_tx_data,
5665fc83 386 apply_tx_config: None,
54d5f336 387 flags: APP_LAYER_PARSER_OPT_UNIDIR_TXS,
4da0d9bd 388 truncate: None,
2e975a04
GL
389 };
390
391 let ip_proto_str = CString::new("udp").unwrap();
392 if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
393 let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
394 ALPROTO_SIP = alproto;
395 if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
396 let _ = AppLayerRegisterParser(&parser, alproto);
397 }
398 } else {
399 SCLogDebug!("Protocol detecter and parser disabled for SIP/UDP.");
400 }
401}