]>
Commit | Line | Data |
---|---|---|
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 | ||
20 | extern crate nom; | |
21 | ||
2f5834cd | 22 | use crate::applayer::{self, *}; |
e68dfa46 JI |
23 | use crate::core; |
24 | use crate::core::{sc_detect_engine_state_free, AppProto, Flow, ALPROTO_UNKNOWN}; | |
e68dfa46 | 25 | use crate::sip::parser::*; |
517ecd68 JI |
26 | use std; |
27 | use std::ffi::{CStr, CString}; | |
2e975a04 GL |
28 | |
29 | #[repr(u32)] | |
30 | pub enum SIPEvent { | |
31 | IncompleteData = 0, | |
32 | InvalidData, | |
33 | } | |
34 | ||
35 | impl 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 | ||
45 | pub struct SIPState { | |
46 | transactions: Vec<SIPTransaction>, | |
47 | tx_id: u64, | |
48 | } | |
49 | ||
50 | pub 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 | ||
61 | impl 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 | ||
145 | impl 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 | ||
160 | impl 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 | 172 | pub 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] | |
179 | pub 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 | 185 | pub 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 | 197 | pub 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 | 203 | pub 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 |
209 | pub 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 | 217 | pub 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 | 227 | pub 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 | 238 | pub 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 | 246 | pub 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 | 271 | pub 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 | 289 | static mut ALPROTO_SIP: AppProto = ALPROTO_UNKNOWN; |
2e975a04 GL |
290 | |
291 | #[no_mangle] | |
363b5f99 | 292 | pub 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 | 307 | pub 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 | 322 | pub 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 | 337 | pub 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 |
351 | export_tx_data_get!(rs_sip_get_tx_data, SIPTransaction); |
352 | ||
517ecd68 | 353 | const PARSER_NAME: &'static [u8] = b"sip\0"; |
2e975a04 GL |
354 | |
355 | #[no_mangle] | |
356 | pub 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 | } |