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