]>
Commit | Line | Data |
---|---|---|
1c8943de FH |
1 | /* Copyright (C) 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 | // Author: Frank Honza <frank.honza@dcso.de> | |
19 | ||
20 | use std; | |
21 | use std::ffi::CString; | |
22 | use std::mem::transmute; | |
23 | use crate::core::{self, ALPROTO_UNKNOWN, AppProto, Flow, IPPROTO_TCP}; | |
1c8943de FH |
24 | use crate::applayer; |
25 | use crate::applayer::*; | |
26 | use nom; | |
27 | use super::parser; | |
28 | ||
29 | static mut ALPROTO_RFB: AppProto = ALPROTO_UNKNOWN; | |
30 | ||
31 | pub struct RFBTransaction { | |
32 | tx_id: u64, | |
33 | pub complete: bool, | |
34 | pub chosen_security_type: Option<u32>, | |
35 | ||
36 | pub tc_server_protocol_version: Option<parser::ProtocolVersion>, | |
37 | pub ts_client_protocol_version: Option<parser::ProtocolVersion>, | |
38 | pub tc_supported_security_types: Option<parser::SupportedSecurityTypes>, | |
39 | pub ts_security_type_selection: Option<parser::SecurityTypeSelection>, | |
40 | pub tc_server_security_type: Option<parser::ServerSecurityType>, | |
41 | pub tc_vnc_challenge: Option<parser::VncAuth>, | |
42 | pub ts_vnc_response: Option<parser::VncAuth>, | |
43 | pub ts_client_init: Option<parser::ClientInit>, | |
44 | pub tc_security_result: Option<parser::SecurityResult>, | |
45 | pub tc_failure_reason: Option<parser::FailureReason>, | |
46 | pub tc_server_init: Option<parser::ServerInit>, | |
47 | ||
1c8943de FH |
48 | de_state: Option<*mut core::DetectEngineState>, |
49 | events: *mut core::AppLayerDecoderEvents, | |
5afe4835 | 50 | tx_data: applayer::AppLayerTxData, |
1c8943de FH |
51 | } |
52 | ||
53 | impl RFBTransaction { | |
54 | pub fn new() -> RFBTransaction { | |
55 | RFBTransaction { | |
56 | tx_id: 0, | |
57 | complete: false, | |
58 | chosen_security_type: None, | |
59 | ||
60 | tc_server_protocol_version: None, | |
61 | ts_client_protocol_version: None, | |
62 | tc_supported_security_types: None, | |
63 | ts_security_type_selection: None, | |
64 | tc_server_security_type: None, | |
65 | tc_vnc_challenge: None, | |
66 | ts_vnc_response: None, | |
67 | ts_client_init: None, | |
68 | tc_security_result: None, | |
69 | tc_failure_reason: None, | |
70 | tc_server_init: None, | |
71 | ||
1c8943de FH |
72 | de_state: None, |
73 | events: std::ptr::null_mut(), | |
5afe4835 | 74 | tx_data: applayer::AppLayerTxData::new(), |
1c8943de FH |
75 | } |
76 | } | |
77 | ||
78 | pub fn free(&mut self) { | |
79 | if self.events != std::ptr::null_mut() { | |
80 | core::sc_app_layer_decoder_events_free_events(&mut self.events); | |
81 | } | |
82 | if let Some(state) = self.de_state { | |
83 | core::sc_detect_engine_state_free(state); | |
84 | } | |
85 | } | |
86 | } | |
87 | ||
88 | impl Drop for RFBTransaction { | |
89 | fn drop(&mut self) { | |
90 | self.free(); | |
91 | } | |
92 | } | |
93 | ||
94 | pub struct RFBState { | |
95 | tx_id: u64, | |
96 | transactions: Vec<RFBTransaction>, | |
97 | state: parser::RFBGlobalState | |
98 | } | |
99 | ||
100 | impl RFBState { | |
101 | pub fn new() -> Self { | |
102 | Self { | |
103 | tx_id: 0, | |
104 | transactions: Vec::new(), | |
105 | state: parser::RFBGlobalState::TCServerProtocolVersion | |
106 | } | |
107 | } | |
108 | ||
109 | // Free a transaction by ID. | |
110 | fn free_tx(&mut self, tx_id: u64) { | |
111 | let len = self.transactions.len(); | |
112 | let mut found = false; | |
113 | let mut index = 0; | |
114 | for i in 0..len { | |
115 | let tx = &self.transactions[i]; | |
116 | if tx.tx_id == tx_id + 1 { | |
117 | found = true; | |
118 | index = i; | |
119 | break; | |
120 | } | |
121 | } | |
122 | if found { | |
123 | self.transactions.remove(index); | |
124 | } | |
125 | } | |
126 | ||
127 | pub fn get_tx(&mut self, tx_id: u64) -> Option<&RFBTransaction> { | |
128 | for tx in &mut self.transactions { | |
129 | if tx.tx_id == tx_id + 1 { | |
130 | return Some(tx); | |
131 | } | |
132 | } | |
133 | return None; | |
134 | } | |
135 | ||
136 | fn new_tx(&mut self) -> RFBTransaction { | |
137 | let mut tx = RFBTransaction::new(); | |
138 | self.tx_id += 1; | |
139 | tx.tx_id = self.tx_id; | |
140 | return tx; | |
141 | } | |
142 | ||
143 | fn get_current_tx(&mut self) -> Option<&mut RFBTransaction> { | |
144 | for tx in &mut self.transactions { | |
145 | if tx.tx_id == self.tx_id { | |
146 | return Some(tx); | |
147 | } | |
148 | } | |
149 | return None; | |
150 | } | |
151 | ||
152 | fn parse_request(&mut self, input: &[u8]) -> AppLayerResult { | |
153 | // We're not interested in empty requests. | |
154 | if input.len() == 0 { | |
155 | return AppLayerResult::ok(); | |
156 | } | |
157 | ||
158 | let mut current = input; | |
bbe9137f | 159 | let mut consumed = 0; |
1c8943de FH |
160 | SCLogDebug!("request_state {}, input_len {}", self.state, input.len()); |
161 | loop { | |
162 | if current.len() == 0 { | |
163 | return AppLayerResult::ok(); | |
164 | } | |
165 | match self.state { | |
166 | parser::RFBGlobalState::TSClientProtocolVersion => { | |
167 | match parser::parse_protocol_version(current) { | |
168 | Ok((rem, request)) => { | |
bbe9137f | 169 | consumed += current.len() - rem.len(); |
1c8943de | 170 | current = rem; |
bbe9137f | 171 | |
1c8943de FH |
172 | if request.major == "003" && request.minor == "003" { |
173 | // in version 3.3 the server decided security type | |
174 | self.state = parser::RFBGlobalState::TCServerSecurityType; | |
175 | } else { | |
176 | self.state = parser::RFBGlobalState::TCSupportedSecurityTypes; | |
177 | } | |
178 | ||
26123e05 SS |
179 | if let Some(current_transaction) = self.get_current_tx() { |
180 | current_transaction.ts_client_protocol_version = Some(request); | |
181 | } else { | |
182 | return AppLayerResult::err(); | |
1c8943de FH |
183 | } |
184 | } | |
bbe9137f | 185 | Err(nom::Err::Incomplete(_)) => { |
186 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
187 | } |
188 | Err(_) => { | |
189 | return AppLayerResult::err(); | |
190 | } | |
191 | } | |
192 | } | |
193 | parser::RFBGlobalState::TSSecurityTypeSelection => { | |
194 | match parser::parse_security_type_selection(current) { | |
195 | Ok((rem, request)) => { | |
bbe9137f | 196 | consumed += current.len() - rem.len(); |
1c8943de FH |
197 | current = rem; |
198 | ||
199 | let chosen_security_type = request.security_type; | |
200 | match chosen_security_type { | |
201 | 2 => self.state = parser::RFBGlobalState::TCVncChallenge, | |
202 | 1 => self.state = parser::RFBGlobalState::TSClientInit, | |
203 | _ => return AppLayerResult::err(), | |
204 | } | |
205 | ||
26123e05 SS |
206 | if let Some(current_transaction) = self.get_current_tx() { |
207 | current_transaction.ts_security_type_selection = Some(request); | |
208 | current_transaction.chosen_security_type = Some(chosen_security_type as u32); | |
209 | } else { | |
210 | return AppLayerResult::err(); | |
1c8943de FH |
211 | } |
212 | } | |
bbe9137f | 213 | Err(nom::Err::Incomplete(_)) => { |
214 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
215 | } |
216 | Err(_) => { | |
217 | return AppLayerResult::err(); | |
218 | } | |
219 | } | |
220 | } | |
221 | parser::RFBGlobalState::TSVncResponse => { | |
222 | match parser::parse_vnc_auth(current) { | |
223 | Ok((rem, request)) => { | |
bbe9137f | 224 | consumed += current.len() - rem.len(); |
1c8943de FH |
225 | current = rem; |
226 | ||
227 | self.state = parser::RFBGlobalState::TCSecurityResult; | |
228 | ||
26123e05 SS |
229 | if let Some(current_transaction) = self.get_current_tx() { |
230 | current_transaction.ts_vnc_response = Some(request); | |
231 | } else { | |
232 | return AppLayerResult::err(); | |
1c8943de FH |
233 | } |
234 | } | |
bbe9137f | 235 | Err(nom::Err::Incomplete(_)) => { |
236 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
237 | } |
238 | Err(_) => { | |
239 | return AppLayerResult::err(); | |
240 | } | |
241 | } | |
242 | } | |
243 | parser::RFBGlobalState::TSClientInit => { | |
244 | match parser::parse_client_init(current) { | |
245 | Ok((rem, request)) => { | |
bbe9137f | 246 | consumed += current.len() - rem.len(); |
1c8943de | 247 | current = rem; |
bbe9137f | 248 | |
1c8943de FH |
249 | self.state = parser::RFBGlobalState::TCServerInit; |
250 | ||
26123e05 SS |
251 | if let Some(current_transaction) = self.get_current_tx() { |
252 | current_transaction.ts_client_init = Some(request); | |
253 | } else { | |
254 | return AppLayerResult::err(); | |
1c8943de FH |
255 | } |
256 | } | |
bbe9137f | 257 | Err(nom::Err::Incomplete(_)) => { |
258 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
259 | } |
260 | Err(_) => { | |
261 | return AppLayerResult::err(); | |
262 | } | |
263 | } | |
264 | } | |
265 | parser::RFBGlobalState::Message => { | |
266 | //todo implement RFB messages, for now we stop here | |
267 | return AppLayerResult::err(); | |
268 | } | |
269 | parser::RFBGlobalState::TCServerProtocolVersion => { | |
270 | SCLogDebug!("Reversed traffic, expected response."); | |
271 | return AppLayerResult::err(); | |
272 | } | |
273 | _ => { | |
274 | SCLogDebug!("Invalid state for request {}", self.state); | |
275 | current = b""; | |
276 | } | |
277 | } | |
278 | } | |
279 | } | |
280 | ||
281 | fn parse_response(&mut self, input: &[u8]) -> AppLayerResult { | |
282 | // We're not interested in empty responses. | |
283 | if input.len() == 0 { | |
284 | return AppLayerResult::ok(); | |
285 | } | |
286 | ||
287 | let mut current = input; | |
bbe9137f | 288 | let mut consumed = 0; |
1c8943de FH |
289 | SCLogDebug!("response_state {}, response_len {}", self.state, input.len()); |
290 | loop { | |
291 | if current.len() == 0 { | |
292 | return AppLayerResult::ok(); | |
293 | } | |
294 | match self.state { | |
295 | parser::RFBGlobalState::TCServerProtocolVersion => { | |
296 | match parser::parse_protocol_version(current) { | |
297 | Ok((rem, request)) => { | |
bbe9137f | 298 | consumed += current.len() - rem.len(); |
1c8943de | 299 | current = rem; |
bbe9137f | 300 | |
1c8943de FH |
301 | self.state = parser::RFBGlobalState::TSClientProtocolVersion; |
302 | let tx = self.new_tx(); | |
303 | self.transactions.push(tx); | |
304 | ||
26123e05 SS |
305 | if let Some(current_transaction) = self.get_current_tx() { |
306 | current_transaction.tc_server_protocol_version = Some(request); | |
307 | } else { | |
308 | return AppLayerResult::err(); | |
1c8943de FH |
309 | } |
310 | } | |
bbe9137f | 311 | Err(nom::Err::Incomplete(_)) => { |
312 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
313 | } |
314 | Err(_) => { | |
315 | return AppLayerResult::err(); | |
316 | } | |
317 | } | |
318 | } | |
319 | parser::RFBGlobalState::TCSupportedSecurityTypes => { | |
320 | match parser::parse_supported_security_types(current) { | |
321 | Ok((rem, request)) => { | |
bbe9137f | 322 | consumed += current.len() - rem.len(); |
1c8943de | 323 | current = rem; |
bbe9137f | 324 | |
1c8943de FH |
325 | SCLogDebug!( |
326 | "supported_security_types: {}, types: {}", request.number_of_types, | |
327 | request.types.iter().map(ToString::to_string).map(|v| v + " ").collect::<String>() | |
328 | ); | |
329 | ||
330 | self.state = parser::RFBGlobalState::TSSecurityTypeSelection; | |
331 | if request.number_of_types == 0 { | |
332 | self.state = parser::RFBGlobalState::TCFailureReason; | |
333 | } | |
334 | ||
26123e05 SS |
335 | if let Some(current_transaction) = self.get_current_tx() { |
336 | current_transaction.tc_supported_security_types = Some(request); | |
337 | } else { | |
338 | return AppLayerResult::err(); | |
1c8943de FH |
339 | } |
340 | } | |
bbe9137f | 341 | Err(nom::Err::Incomplete(_)) => { |
342 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
343 | } |
344 | Err(_) => { | |
345 | return AppLayerResult::err(); | |
346 | } | |
347 | } | |
348 | } | |
349 | parser::RFBGlobalState::TCServerSecurityType => { | |
350 | // In RFB 3.3, the server decides the authentication type | |
351 | match parser::parse_server_security_type(current) { | |
352 | Ok((rem, request)) => { | |
bbe9137f | 353 | consumed += current.len() - rem.len(); |
1c8943de | 354 | current = rem; |
bbe9137f | 355 | |
1c8943de FH |
356 | let chosen_security_type = request.security_type; |
357 | SCLogDebug!("chosen_security_type: {}", chosen_security_type); | |
358 | match chosen_security_type { | |
359 | 0 => self.state = parser::RFBGlobalState::TCFailureReason, | |
360 | 1 => self.state = parser::RFBGlobalState::TSClientInit, | |
361 | 2 => self.state = parser::RFBGlobalState::TCVncChallenge, | |
362 | _ => { | |
363 | // TODO Event unknown security type | |
364 | return AppLayerResult::err(); | |
365 | } | |
366 | } | |
367 | ||
26123e05 SS |
368 | if let Some(current_transaction) = self.get_current_tx() { |
369 | current_transaction.tc_server_security_type = Some(request); | |
370 | current_transaction.chosen_security_type = Some(chosen_security_type); | |
371 | } else { | |
372 | return AppLayerResult::err(); | |
1c8943de FH |
373 | } |
374 | } | |
bbe9137f | 375 | Err(nom::Err::Incomplete(_)) => { |
376 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
377 | } |
378 | Err(_) => { | |
379 | return AppLayerResult::err(); | |
380 | } | |
381 | } | |
382 | } | |
383 | parser::RFBGlobalState::TCVncChallenge => { | |
384 | match parser::parse_vnc_auth(current) { | |
385 | Ok((rem, request)) => { | |
bbe9137f | 386 | consumed += current.len() - rem.len(); |
1c8943de FH |
387 | current = rem; |
388 | ||
389 | self.state = parser::RFBGlobalState::TSVncResponse; | |
390 | ||
26123e05 SS |
391 | if let Some(current_transaction) = self.get_current_tx() { |
392 | current_transaction.tc_vnc_challenge = Some(request); | |
393 | } else { | |
394 | return AppLayerResult::err(); | |
1c8943de FH |
395 | } |
396 | } | |
bbe9137f | 397 | Err(nom::Err::Incomplete(_)) => { |
398 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
399 | } |
400 | Err(_) => { | |
401 | return AppLayerResult::err(); | |
402 | } | |
403 | } | |
404 | } | |
405 | parser::RFBGlobalState::TCSecurityResult => { | |
406 | match parser::parse_security_result(current) { | |
407 | Ok((rem, request)) => { | |
bbe9137f | 408 | consumed += current.len() - rem.len(); |
1c8943de FH |
409 | current = rem; |
410 | ||
411 | if request.status == 0 { | |
412 | self.state = parser::RFBGlobalState::TSClientInit; | |
413 | ||
26123e05 SS |
414 | if let Some(current_transaction) = self.get_current_tx() { |
415 | current_transaction.tc_security_result = Some(request); | |
416 | } else { | |
417 | return AppLayerResult::err(); | |
1c8943de FH |
418 | } |
419 | } else if request.status == 1 { | |
420 | self.state = parser::RFBGlobalState::TCFailureReason; | |
421 | } else { | |
422 | // TODO: Event: unknown security result value | |
423 | } | |
424 | } | |
bbe9137f | 425 | Err(nom::Err::Incomplete(_)) => { |
426 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
427 | } |
428 | Err(_) => { | |
429 | return AppLayerResult::err(); | |
430 | } | |
431 | } | |
432 | } | |
433 | parser::RFBGlobalState::TCFailureReason => { | |
434 | match parser::parse_failure_reason(current) { | |
435 | Ok((_rem, request)) => { | |
26123e05 SS |
436 | if let Some(current_transaction) = self.get_current_tx() { |
437 | current_transaction.tc_failure_reason = Some(request); | |
438 | } else { | |
439 | return AppLayerResult::err(); | |
1c8943de FH |
440 | } |
441 | return AppLayerResult::err(); | |
442 | } | |
bbe9137f | 443 | Err(nom::Err::Incomplete(_)) => { |
444 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
445 | } |
446 | Err(_) => { | |
447 | return AppLayerResult::err(); | |
448 | } | |
449 | } | |
450 | } | |
451 | parser::RFBGlobalState::TCServerInit => { | |
452 | match parser::parse_server_init(current) { | |
453 | Ok((rem, request)) => { | |
bbe9137f | 454 | consumed += current.len() - rem.len(); |
1c8943de | 455 | current = rem; |
bbe9137f | 456 | |
1c8943de FH |
457 | self.state = parser::RFBGlobalState::Message; |
458 | ||
26123e05 SS |
459 | if let Some(current_transaction) = self.get_current_tx() { |
460 | current_transaction.tc_server_init = Some(request); | |
461 | // connection initialization is complete and parsed | |
462 | current_transaction.complete = true; | |
463 | } else { | |
464 | return AppLayerResult::err(); | |
1c8943de FH |
465 | } |
466 | } | |
bbe9137f | 467 | Err(nom::Err::Incomplete(_)) => { |
468 | return AppLayerResult::incomplete(consumed as u32, (current.len() + 1) as u32); | |
1c8943de FH |
469 | } |
470 | Err(_) => { | |
471 | return AppLayerResult::err(); | |
472 | } | |
473 | } | |
474 | } | |
475 | parser::RFBGlobalState::Message => { | |
476 | //todo implement RFB messages, for now we stop here | |
477 | return AppLayerResult::err(); | |
478 | } | |
479 | _ => { | |
480 | SCLogDebug!("Invalid state for response"); | |
481 | return AppLayerResult::err(); | |
482 | } | |
483 | } | |
484 | } | |
485 | } | |
486 | ||
487 | fn tx_iterator( | |
488 | &mut self, | |
489 | min_tx_id: u64, | |
490 | state: &mut u64, | |
491 | ) -> Option<(&RFBTransaction, u64, bool)> { | |
492 | let mut index = *state as usize; | |
493 | let len = self.transactions.len(); | |
494 | ||
495 | while index < len { | |
496 | let tx = &self.transactions[index]; | |
497 | if tx.tx_id < min_tx_id + 1 { | |
498 | index += 1; | |
499 | continue; | |
500 | } | |
501 | *state = index as u64; | |
502 | return Some((tx, tx.tx_id - 1, (len - index) > 1)); | |
503 | } | |
504 | ||
505 | return None; | |
506 | } | |
507 | } | |
508 | ||
509 | // C exports. | |
510 | ||
511 | export_tx_get_detect_state!( | |
512 | rs_rfb_tx_get_detect_state, | |
513 | RFBTransaction | |
514 | ); | |
515 | export_tx_set_detect_state!( | |
516 | rs_rfb_tx_set_detect_state, | |
517 | RFBTransaction | |
518 | ); | |
519 | ||
520 | #[no_mangle] | |
547d6c2d | 521 | pub extern "C" fn rs_rfb_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void { |
1c8943de FH |
522 | let state = RFBState::new(); |
523 | let boxed = Box::new(state); | |
524 | return unsafe { transmute(boxed) }; | |
525 | } | |
526 | ||
527 | #[no_mangle] | |
528 | pub extern "C" fn rs_rfb_state_free(state: *mut std::os::raw::c_void) { | |
529 | // Just unbox... | |
530 | let _drop: Box<RFBState> = unsafe { transmute(state) }; | |
531 | } | |
532 | ||
533 | #[no_mangle] | |
534 | pub extern "C" fn rs_rfb_state_tx_free( | |
535 | state: *mut std::os::raw::c_void, | |
536 | tx_id: u64, | |
537 | ) { | |
538 | let state = cast_pointer!(state, RFBState); | |
539 | state.free_tx(tx_id); | |
540 | } | |
541 | ||
542 | #[no_mangle] | |
543 | pub extern "C" fn rs_rfb_parse_request( | |
544 | _flow: *const Flow, | |
545 | state: *mut std::os::raw::c_void, | |
546 | _pstate: *mut std::os::raw::c_void, | |
547 | input: *const u8, | |
548 | input_len: u32, | |
549 | _data: *const std::os::raw::c_void, | |
550 | _flags: u8, | |
551 | ) -> AppLayerResult { | |
552 | let state = cast_pointer!(state, RFBState); | |
553 | let buf = build_slice!(input, input_len as usize); | |
554 | return state.parse_request(buf); | |
555 | } | |
556 | ||
557 | #[no_mangle] | |
558 | pub extern "C" fn rs_rfb_parse_response( | |
559 | _flow: *const Flow, | |
560 | state: *mut std::os::raw::c_void, | |
561 | _pstate: *mut std::os::raw::c_void, | |
562 | input: *const u8, | |
563 | input_len: u32, | |
564 | _data: *const std::os::raw::c_void, | |
565 | _flags: u8, | |
566 | ) -> AppLayerResult { | |
567 | let state = cast_pointer!(state, RFBState); | |
568 | let buf = build_slice!(input, input_len as usize); | |
569 | return state.parse_response(buf); | |
570 | } | |
571 | ||
572 | #[no_mangle] | |
573 | pub extern "C" fn rs_rfb_state_get_tx( | |
574 | state: *mut std::os::raw::c_void, | |
575 | tx_id: u64, | |
576 | ) -> *mut std::os::raw::c_void { | |
577 | let state = cast_pointer!(state, RFBState); | |
578 | match state.get_tx(tx_id) { | |
579 | Some(tx) => { | |
580 | return unsafe { transmute(tx) }; | |
581 | } | |
582 | None => { | |
583 | return std::ptr::null_mut(); | |
584 | } | |
585 | } | |
586 | } | |
587 | ||
588 | #[no_mangle] | |
589 | pub extern "C" fn rs_rfb_state_get_tx_count( | |
590 | state: *mut std::os::raw::c_void, | |
591 | ) -> u64 { | |
592 | let state = cast_pointer!(state, RFBState); | |
593 | return state.tx_id; | |
594 | } | |
595 | ||
596 | #[no_mangle] | |
597 | pub extern "C" fn rs_rfb_state_progress_completion_status( | |
598 | _direction: u8, | |
599 | ) -> std::os::raw::c_int { | |
600 | // This parser uses 1 to signal transaction completion status. | |
601 | return 1; | |
602 | } | |
603 | ||
604 | #[no_mangle] | |
605 | pub extern "C" fn rs_rfb_tx_get_alstate_progress( | |
606 | tx: *mut std::os::raw::c_void, | |
607 | _direction: u8, | |
608 | ) -> std::os::raw::c_int { | |
609 | let tx = cast_pointer!(tx, RFBTransaction); | |
610 | if tx.complete { | |
611 | return 1; | |
612 | } | |
613 | return 0; | |
614 | } | |
615 | ||
1c8943de FH |
616 | #[no_mangle] |
617 | pub extern "C" fn rs_rfb_state_get_events( | |
618 | tx: *mut std::os::raw::c_void | |
619 | ) -> *mut core::AppLayerDecoderEvents { | |
620 | let tx = cast_pointer!(tx, RFBTransaction); | |
621 | return tx.events; | |
622 | } | |
623 | ||
624 | #[no_mangle] | |
625 | pub extern "C" fn rs_rfb_state_get_event_info( | |
626 | _event_name: *const std::os::raw::c_char, | |
627 | _event_id: *mut std::os::raw::c_int, | |
628 | _event_type: *mut core::AppLayerEventType, | |
629 | ) -> std::os::raw::c_int { | |
630 | return -1; | |
631 | } | |
632 | ||
633 | #[no_mangle] | |
634 | pub extern "C" fn rs_rfb_state_get_event_info_by_id(_event_id: std::os::raw::c_int, | |
635 | _event_name: *mut *const std::os::raw::c_char, | |
636 | _event_type: *mut core::AppLayerEventType | |
637 | ) -> i8 { | |
638 | return -1; | |
639 | } | |
640 | #[no_mangle] | |
641 | pub extern "C" fn rs_rfb_state_get_tx_iterator( | |
642 | _ipproto: u8, | |
643 | _alproto: AppProto, | |
644 | state: *mut std::os::raw::c_void, | |
645 | min_tx_id: u64, | |
646 | _max_tx_id: u64, | |
647 | istate: &mut u64, | |
648 | ) -> applayer::AppLayerGetTxIterTuple { | |
649 | let state = cast_pointer!(state, RFBState); | |
650 | match state.tx_iterator(min_tx_id, istate) { | |
651 | Some((tx, out_tx_id, has_next)) => { | |
652 | let c_tx = unsafe { transmute(tx) }; | |
653 | let ires = applayer::AppLayerGetTxIterTuple::with_values( | |
654 | c_tx, | |
655 | out_tx_id, | |
656 | has_next, | |
657 | ); | |
658 | return ires; | |
659 | } | |
660 | None => { | |
661 | return applayer::AppLayerGetTxIterTuple::not_found(); | |
662 | } | |
663 | } | |
664 | } | |
665 | ||
666 | // Parser name as a C style string. | |
667 | const PARSER_NAME: &'static [u8] = b"rfb\0"; | |
668 | ||
5afe4835 | 669 | export_tx_data_get!(rs_rfb_get_tx_data, RFBTransaction); |
1c8943de FH |
670 | |
671 | #[no_mangle] | |
672 | pub unsafe extern "C" fn rs_rfb_register_parser() { | |
673 | let default_port = CString::new("[5900]").unwrap(); | |
674 | let parser = RustParser { | |
675 | name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char, | |
676 | default_port: default_port.as_ptr(), | |
677 | ipproto: IPPROTO_TCP, | |
678 | probe_ts: None, | |
679 | probe_tc: None, | |
680 | min_depth: 0, | |
681 | max_depth: 16, | |
682 | state_new: rs_rfb_state_new, | |
683 | state_free: rs_rfb_state_free, | |
684 | tx_free: rs_rfb_state_tx_free, | |
685 | parse_ts: rs_rfb_parse_request, | |
686 | parse_tc: rs_rfb_parse_response, | |
687 | get_tx_count: rs_rfb_state_get_tx_count, | |
688 | get_tx: rs_rfb_state_get_tx, | |
689 | tx_get_comp_st: rs_rfb_state_progress_completion_status, | |
690 | tx_get_progress: rs_rfb_tx_get_alstate_progress, | |
1c8943de FH |
691 | get_de_state: rs_rfb_tx_get_detect_state, |
692 | set_de_state: rs_rfb_tx_set_detect_state, | |
693 | get_events: Some(rs_rfb_state_get_events), | |
694 | get_eventinfo: Some(rs_rfb_state_get_event_info), | |
695 | get_eventinfo_byid : Some(rs_rfb_state_get_event_info_by_id), | |
696 | localstorage_new: None, | |
697 | localstorage_free: None, | |
1c8943de FH |
698 | get_files: None, |
699 | get_tx_iterator: Some(rs_rfb_state_get_tx_iterator), | |
c94a5e63 | 700 | get_tx_data: rs_rfb_get_tx_data, |
5665fc83 | 701 | apply_tx_config: None, |
53aa967e | 702 | flags: 0, |
1c8943de FH |
703 | }; |
704 | ||
705 | let ip_proto_str = CString::new("tcp").unwrap(); | |
706 | ||
707 | if AppLayerProtoDetectConfProtoDetectionEnabled( | |
708 | ip_proto_str.as_ptr(), | |
709 | parser.name, | |
710 | ) != 0 | |
711 | { | |
712 | let alproto = AppLayerRegisterProtocolDetection(&parser, 1); | |
713 | ALPROTO_RFB = alproto; | |
714 | if AppLayerParserConfParserEnabled( | |
715 | ip_proto_str.as_ptr(), | |
716 | parser.name, | |
717 | ) != 0 | |
718 | { | |
719 | let _ = AppLayerRegisterParser(&parser, alproto); | |
720 | } | |
721 | SCLogDebug!("Rust rfb parser registered."); | |
722 | } else { | |
723 | SCLogDebug!("Protocol detector and parser disabled for RFB."); | |
724 | } | |
725 | } |