]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/rfb/rfb.rs
app-layer: include decoder events in app-layer tx data
[people/ms/suricata.git] / rust / src / rfb / rfb.rs
CommitLineData
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
20use std;
21use std::ffi::CString;
7732efbe 22use crate::core::{ALPROTO_UNKNOWN, AppProto, Flow, IPPROTO_TCP};
1c8943de
FH
23use crate::applayer;
24use crate::applayer::*;
25use nom;
26use super::parser;
27
28static mut ALPROTO_RFB: AppProto = ALPROTO_UNKNOWN;
29
30pub 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
50impl Transaction for RFBTransaction {
51 fn id(&self) -> u64 {
52 self.tx_id
53 }
54}
55
1c8943de
FH
56impl 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
80pub struct RFBState {
81 tx_id: u64,
82 transactions: Vec<RFBTransaction>,
83 state: parser::RFBGlobalState
84}
85
0188a01d
JI
86impl State<RFBTransaction> for RFBState {
87 fn get_transactions(&self) -> &[RFBTransaction] {
88 &self.transactions
89 }
90}
91
1c8943de
FH
92impl 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 483pub 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]
490pub 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 496pub 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 505pub 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 520pub 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 535pub 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 551pub 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 559pub 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.
571const PARSER_NAME: &'static [u8] = b"rfb\0";
572
5afe4835 573export_tx_data_get!(rs_rfb_get_tx_data, RFBTransaction);
1c8943de
FH
574
575#[no_mangle]
576pub 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}