Coverage Report

Created: 2025-07-23 07:29

/src/suricata7/rust/src/rfb/rfb.rs
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2020-2023 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
//         Sascha Steinbiss <sascha.steinbiss@dcso.de>
20
21
use super::parser;
22
use crate::applayer;
23
use crate::applayer::*;
24
use crate::core::{AppProto, Flow, ALPROTO_UNKNOWN, IPPROTO_TCP};
25
use crate::frames::*;
26
use nom7::Err;
27
use std;
28
use std::ffi::CString;
29
30
static mut ALPROTO_RFB: AppProto = ALPROTO_UNKNOWN;
31
32
96
#[derive(FromPrimitive, Debug, AppLayerEvent)]
Unexecuted instantiation: <suricata::rfb::rfb::RFBEvent as num_traits::cast::FromPrimitive>::from_i64
Unexecuted instantiation: <suricata::rfb::rfb::RFBEvent as num_traits::cast::FromPrimitive>::from_u64
<suricata::rfb::rfb::RFBEvent as suricata::applayer::AppLayerEvent>::from_id
Line
Count
Source
32
16
#[derive(FromPrimitive, Debug, AppLayerEvent)]
<suricata::rfb::rfb::RFBEvent as suricata::applayer::AppLayerEvent>::as_i32
Line
Count
Source
32
30
#[derive(FromPrimitive, Debug, AppLayerEvent)]
<suricata::rfb::rfb::RFBEvent as suricata::applayer::AppLayerEvent>::to_cstring
Line
Count
Source
32
16
#[derive(FromPrimitive, Debug, AppLayerEvent)]
<suricata::rfb::rfb::RFBEvent as suricata::applayer::AppLayerEvent>::from_string
Line
Count
Source
32
34
#[derive(FromPrimitive, Debug, AppLayerEvent)]
<suricata::rfb::rfb::RFBEvent as suricata::applayer::AppLayerEvent>::get_event_info
Line
Count
Source
32
34
#[derive(FromPrimitive, Debug, AppLayerEvent)]
<suricata::rfb::rfb::RFBEvent as suricata::applayer::AppLayerEvent>::get_event_info_by_id
Line
Count
Source
32
16
#[derive(FromPrimitive, Debug, AppLayerEvent)]
33
pub enum RFBEvent {
34
    UnimplementedSecurityType,
35
    UnknownSecurityResult,
36
    MalformedMessage,
37
    ConfusedState,
38
}
39
40
9
#[derive(AppLayerFrameType)]
Unexecuted instantiation: <suricata::rfb::rfb::RFBFrameType as suricata::applayer::AppLayerFrameType>::from_u8
<suricata::rfb::rfb::RFBFrameType as suricata::applayer::AppLayerFrameType>::as_u8
Line
Count
Source
40
6
#[derive(AppLayerFrameType)]
Unexecuted instantiation: <suricata::rfb::rfb::RFBFrameType as suricata::applayer::AppLayerFrameType>::to_cstring
<suricata::rfb::rfb::RFBFrameType as suricata::applayer::AppLayerFrameType>::from_str
Line
Count
Source
40
9
#[derive(AppLayerFrameType)]
41
pub enum RFBFrameType {
42
    Pdu,
43
}
44
pub struct RFBTransaction {
45
    tx_id: u64,
46
    pub complete: bool,
47
    pub chosen_security_type: Option<u32>,
48
49
    pub tc_server_protocol_version: Option<parser::ProtocolVersion>,
50
    pub ts_client_protocol_version: Option<parser::ProtocolVersion>,
51
    pub tc_supported_security_types: Option<parser::SupportedSecurityTypes>,
52
    pub ts_security_type_selection: Option<parser::SecurityTypeSelection>,
53
    pub tc_server_security_type: Option<parser::ServerSecurityType>,
54
    pub tc_vnc_challenge: Option<parser::VncAuth>,
55
    pub ts_vnc_response: Option<parser::VncAuth>,
56
    pub ts_client_init: Option<parser::ClientInit>,
57
    pub tc_security_result: Option<parser::SecurityResult>,
58
    pub tc_failure_reason: Option<parser::FailureReason>,
59
    pub tc_server_init: Option<parser::ServerInit>,
60
61
    tx_data: applayer::AppLayerTxData,
62
}
63
64
impl Transaction for RFBTransaction {
65
25.0k
    fn id(&self) -> u64 {
66
25.0k
        self.tx_id
67
25.0k
    }
68
}
69
70
impl Default for RFBTransaction {
71
0
    fn default() -> Self {
72
0
        Self::new()
73
0
    }
74
}
75
76
impl RFBTransaction {
77
1.25k
    pub fn new() -> Self {
78
1.25k
        Self {
79
1.25k
            tx_id: 0,
80
1.25k
            complete: false,
81
1.25k
            chosen_security_type: None,
82
1.25k
83
1.25k
            tc_server_protocol_version: None,
84
1.25k
            ts_client_protocol_version: None,
85
1.25k
            tc_supported_security_types: None,
86
1.25k
            ts_security_type_selection: None,
87
1.25k
            tc_server_security_type: None,
88
1.25k
            tc_vnc_challenge: None,
89
1.25k
            ts_vnc_response: None,
90
1.25k
            ts_client_init: None,
91
1.25k
            tc_security_result: None,
92
1.25k
            tc_failure_reason: None,
93
1.25k
            tc_server_init: None,
94
1.25k
95
1.25k
            tx_data: applayer::AppLayerTxData::new(),
96
1.25k
        }
97
1.25k
    }
98
99
436
    fn set_event(&mut self, event: RFBEvent) {
100
436
        self.tx_data.set_event(event as u8);
101
436
    }
102
}
103
104
pub struct RFBState {
105
    state_data: AppLayerStateData,
106
    tx_id: u64,
107
    transactions: Vec<RFBTransaction>,
108
    state: parser::RFBGlobalState,
109
}
110
111
impl State<RFBTransaction> for RFBState {
112
20.4k
    fn get_transaction_count(&self) -> usize {
113
20.4k
        self.transactions.len()
114
20.4k
    }
115
116
12.5k
    fn get_transaction_by_index(&self, index: usize) -> Option<&RFBTransaction> {
117
12.5k
        self.transactions.get(index)
118
12.5k
    }
119
}
120
121
impl Default for RFBState {
122
0
    fn default() -> Self {
123
0
        Self::new()
124
0
    }
125
}
126
127
impl RFBState {
128
1.57k
    pub fn new() -> Self {
129
1.57k
        Self {
130
1.57k
            state_data: AppLayerStateData::new(),
131
1.57k
            tx_id: 0,
132
1.57k
            transactions: Vec::new(),
133
1.57k
            state: parser::RFBGlobalState::TCServerProtocolVersion,
134
1.57k
        }
135
1.57k
    }
136
137
    // Free a transaction by ID.
138
44
    fn free_tx(&mut self, tx_id: u64) {
139
44
        let len = self.transactions.len();
140
44
        let mut found = false;
141
44
        let mut index = 0;
142
44
        for i in 0..len {
143
44
            let tx = &self.transactions[i];
144
44
            if tx.tx_id == tx_id + 1 {
145
44
                found = true;
146
44
                index = i;
147
44
                break;
148
0
            }
149
        }
150
44
        if found {
151
44
            self.transactions.remove(index);
152
44
        }
153
44
    }
154
155
18
    pub fn get_tx(&mut self, tx_id: u64) -> Option<&RFBTransaction> {
156
18
        self.transactions.iter().find(|tx| tx.tx_id == tx_id + 1)
157
18
    }
158
159
1.25k
    fn new_tx(&mut self) -> RFBTransaction {
160
1.25k
        let mut tx = RFBTransaction::new();
161
1.25k
        self.tx_id += 1;
162
1.25k
        tx.tx_id = self.tx_id;
163
1.25k
        return tx;
164
1.25k
    }
165
166
6.47k
    fn get_current_tx(&mut self) -> Option<&mut RFBTransaction> {
167
6.47k
        let tx_id = self.tx_id;
168
6.47k
        let r = self.transactions.iter_mut().find(|tx| tx.tx_id == tx_id);
169
6.47k
        if let Some(tx) = r {
170
6.31k
            tx.tx_data.updated_tc = true;
171
6.31k
            tx.tx_data.updated_ts = true;
172
6.31k
            return Some(tx);
173
159
        }
174
159
        return None;
175
6.47k
    }
176
177
4.65k
    fn parse_request(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> AppLayerResult {
178
4.65k
        let input = stream_slice.as_slice();
179
4.65k
180
4.65k
        // We're not interested in empty requests.
181
4.65k
        if input.is_empty() {
182
0
            return AppLayerResult::ok();
183
4.65k
        }
184
4.65k
185
4.65k
        let mut current = input;
186
4.65k
        let mut consumed = 0;
187
        SCLogDebug!("request_state {}, input_len {}", self.state, input.len());
188
        loop {
189
6.63k
            if current.is_empty() {
190
1.45k
                return AppLayerResult::ok();
191
5.18k
            }
192
5.18k
            match self.state {
193
                parser::RFBGlobalState::TSClientProtocolVersion => {
194
1.53k
                    match parser::parse_protocol_version(current) {
195
1.00k
                        Ok((rem, request)) => {
196
1.00k
                            consumed += current.len() - rem.len();
197
1.00k
                            let _pdu = Frame::new(
198
1.00k
                                flow,
199
1.00k
                                &stream_slice,
200
1.00k
                                current,
201
1.00k
                                consumed as i64,
202
1.00k
                                RFBFrameType::Pdu as u8,
203
1.00k
                            );
204
1.00k
205
1.00k
                            current = rem;
206
1.00k
207
1.00k
                            if request.major == "003" && request.minor == "003" {
208
184
                                // in version 3.3 the server decided security type
209
184
                                self.state = parser::RFBGlobalState::TCServerSecurityType;
210
823
                            } else {
211
823
                                self.state = parser::RFBGlobalState::TCSupportedSecurityTypes;
212
823
                            }
213
214
1.00k
                            if let Some(current_transaction) = self.get_current_tx() {
215
1.00k
                                current_transaction.ts_client_protocol_version = Some(request);
216
1.00k
                            } else {
217
0
                                debug_validate_fail!(
218
0
                                    "no transaction set at protocol selection stage"
219
                                );
220
                            }
221
                        }
222
                        Err(Err::Incomplete(_)) => {
223
523
                            return AppLayerResult::incomplete(
224
523
                                consumed as u32,
225
523
                                (current.len() + 1) as u32,
226
523
                            );
227
                        }
228
                        Err(_) => {
229
                            // We even failed to parse the protocol version.
230
5
                            return AppLayerResult::err();
231
                        }
232
                    }
233
                }
234
                parser::RFBGlobalState::TSSecurityTypeSelection => {
235
468
                    match parser::parse_security_type_selection(current) {
236
468
                        Ok((rem, request)) => {
237
468
                            consumed += current.len() - rem.len();
238
468
                            let _pdu = Frame::new(
239
468
                                flow,
240
468
                                &stream_slice,
241
468
                                current,
242
468
                                consumed as i64,
243
468
                                RFBFrameType::Pdu as u8,
244
468
                            );
245
468
246
468
                            current = rem;
247
468
248
468
                            let chosen_security_type = request.security_type;
249
250
468
                            if let Some(current_transaction) = self.get_current_tx() {
251
468
                                current_transaction.ts_security_type_selection = Some(request);
252
468
                                current_transaction.chosen_security_type =
253
468
                                    Some(chosen_security_type as u32);
254
468
                            } else {
255
0
                                debug_validate_fail!("no transaction set at security type stage");
256
                            }
257
258
468
                            match chosen_security_type {
259
7
                                2 => self.state = parser::RFBGlobalState::TCVncChallenge,
260
455
                                1 => self.state = parser::RFBGlobalState::TSClientInit,
261
                                _ => {
262
6
                                    if let Some(current_transaction) = self.get_current_tx() {
263
6
                                        current_transaction
264
6
                                            .set_event(RFBEvent::UnimplementedSecurityType);
265
6
                                    }
266
                                    // We have just have seen a security type we don't know about.
267
                                    // This is not bad per se, it might just mean this is a
268
                                    // proprietary one not in the spec.
269
                                    // Continue the flow but stop trying to map the protocol.
270
6
                                    self.state = parser::RFBGlobalState::Skip;
271
6
                                    return AppLayerResult::ok();
272
                                }
273
                            }
274
                        }
275
                        Err(Err::Incomplete(_)) => {
276
0
                            return AppLayerResult::incomplete(
277
0
                                consumed as u32,
278
0
                                (current.len() + 1) as u32,
279
0
                            );
280
                        }
281
                        Err(_) => {
282
0
                            if let Some(current_transaction) = self.get_current_tx() {
283
0
                                current_transaction.set_event(RFBEvent::MalformedMessage);
284
0
                                current_transaction.complete = true;
285
0
                            }
286
                            // We failed to parse the security type.
287
                            // Continue the flow but stop trying to map the protocol.
288
0
                            self.state = parser::RFBGlobalState::Skip;
289
0
                            return AppLayerResult::ok();
290
                        }
291
                    }
292
                }
293
295
                parser::RFBGlobalState::TSVncResponse => match parser::parse_vnc_auth(current) {
294
58
                    Ok((rem, request)) => {
295
58
                        consumed += current.len() - rem.len();
296
58
                        let _pdu = Frame::new(
297
58
                            flow,
298
58
                            &stream_slice,
299
58
                            current,
300
58
                            consumed as i64,
301
58
                            RFBFrameType::Pdu as u8,
302
58
                        );
303
58
304
58
                        current = rem;
305
58
306
58
                        self.state = parser::RFBGlobalState::TCSecurityResult;
307
308
58
                        if let Some(current_transaction) = self.get_current_tx() {
309
58
                            current_transaction.ts_vnc_response = Some(request);
310
58
                        } else {
311
0
                            debug_validate_fail!("no transaction set at security result stage");
312
                        }
313
                    }
314
                    Err(Err::Incomplete(_)) => {
315
237
                        return AppLayerResult::incomplete(
316
237
                            consumed as u32,
317
237
                            (current.len() + 1) as u32,
318
237
                        );
319
                    }
320
                    Err(_) => {
321
0
                        if let Some(current_transaction) = self.get_current_tx() {
322
0
                            current_transaction.set_event(RFBEvent::MalformedMessage);
323
0
                            current_transaction.complete = true;
324
0
                        }
325
                        // Continue the flow but stop trying to map the protocol.
326
0
                        self.state = parser::RFBGlobalState::Skip;
327
0
                        return AppLayerResult::ok();
328
                    }
329
                },
330
456
                parser::RFBGlobalState::TSClientInit => match parser::parse_client_init(current) {
331
456
                    Ok((rem, request)) => {
332
456
                        consumed += current.len() - rem.len();
333
456
                        let _pdu = Frame::new(
334
456
                            flow,
335
456
                            &stream_slice,
336
456
                            current,
337
456
                            consumed as i64,
338
456
                            RFBFrameType::Pdu as u8,
339
456
                        );
340
456
341
456
                        current = rem;
342
456
343
456
                        self.state = parser::RFBGlobalState::TCServerInit;
344
345
456
                        if let Some(current_transaction) = self.get_current_tx() {
346
456
                            current_transaction.ts_client_init = Some(request);
347
456
                        } else {
348
0
                            debug_validate_fail!("no transaction set at client init stage");
349
                        }
350
                    }
351
                    Err(Err::Incomplete(_)) => {
352
0
                        return AppLayerResult::incomplete(
353
0
                            consumed as u32,
354
0
                            (current.len() + 1) as u32,
355
0
                        );
356
                    }
357
                    Err(_) => {
358
0
                        if let Some(current_transaction) = self.get_current_tx() {
359
0
                            current_transaction.set_event(RFBEvent::MalformedMessage);
360
0
                            current_transaction.complete = true;
361
0
                        }
362
                        // We failed to parse the client init.
363
                        // Continue the flow but stop trying to map the protocol.
364
0
                        self.state = parser::RFBGlobalState::Skip;
365
0
                        return AppLayerResult::ok();
366
                    }
367
                },
368
                parser::RFBGlobalState::Skip => {
369
                    // End of parseable handshake reached, skip rest of traffic
370
2.18k
                    return AppLayerResult::ok();
371
                }
372
                _ => {
373
                    // We have gotten out of sync with the expected state flow.
374
                    // This could happen since we use a global state (i.e. that
375
                    // is used for both directions), but if traffic can not be
376
                    // parsed as expected elsewhere, we might not have advanced
377
                    // a state for one direction but received data in the
378
                    // "unexpected" direction, causing the parser to end up
379
                    // here. Let's stop trying to parse the traffic but still
380
                    // accept it.
381
                    SCLogDebug!("Invalid state for request: {}", self.state);
382
241
                    if let Some(current_transaction) = self.get_current_tx() {
383
82
                        current_transaction.set_event(RFBEvent::ConfusedState);
384
82
                        current_transaction.complete = true;
385
159
                    }
386
241
                    self.state = parser::RFBGlobalState::Skip;
387
241
                    return AppLayerResult::ok();
388
                }
389
            }
390
        }
391
4.65k
    }
392
393
15.1k
    fn parse_response(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> AppLayerResult {
394
15.1k
        let input = stream_slice.as_slice();
395
15.1k
        // We're not interested in empty responses.
396
15.1k
        if input.is_empty() {
397
0
            return AppLayerResult::ok();
398
15.1k
        }
399
15.1k
400
15.1k
        let mut current = input;
401
15.1k
        let mut consumed = 0;
402
        SCLogDebug!(
403
            "response_state {}, response_len {}",
404
            self.state,
405
            input.len()
406
        );
407
        loop {
408
17.5k
            if current.is_empty() {
409
1.63k
                return AppLayerResult::ok();
410
15.9k
            }
411
15.9k
            match self.state {
412
                parser::RFBGlobalState::TCServerProtocolVersion => {
413
3.24k
                    match parser::parse_protocol_version(current) {
414
1.25k
                        Ok((rem, request)) => {
415
1.25k
                            consumed += current.len() - rem.len();
416
1.25k
                            let _pdu = Frame::new(
417
1.25k
                                flow,
418
1.25k
                                &stream_slice,
419
1.25k
                                current,
420
1.25k
                                consumed as i64,
421
1.25k
                                RFBFrameType::Pdu as u8,
422
1.25k
                            );
423
1.25k
424
1.25k
                            current = rem;
425
1.25k
426
1.25k
                            self.state = parser::RFBGlobalState::TSClientProtocolVersion;
427
1.25k
                            let tx = self.new_tx();
428
1.25k
                            self.transactions.push(tx);
429
430
1.25k
                            if let Some(current_transaction) = self.get_current_tx() {
431
1.25k
                                current_transaction.tc_server_protocol_version = Some(request);
432
1.25k
                            } else {
433
0
                                debug_validate_fail!("no transaction set but we just set one");
434
                            }
435
                        }
436
                        Err(Err::Incomplete(_)) => {
437
1.90k
                            return AppLayerResult::incomplete(
438
1.90k
                                consumed as u32,
439
1.90k
                                (current.len() + 1) as u32,
440
1.90k
                            );
441
                        }
442
                        Err(_) => {
443
                            // We even failed to parse the protocol version.
444
85
                            return AppLayerResult::err();
445
                        }
446
                    }
447
                }
448
                parser::RFBGlobalState::TCSupportedSecurityTypes => {
449
1.18k
                    match parser::parse_supported_security_types(current) {
450
732
                        Ok((rem, request)) => {
451
732
                            consumed += current.len() - rem.len();
452
732
                            let _pdu = Frame::new(
453
732
                                flow,
454
732
                                &stream_slice,
455
732
                                current,
456
732
                                consumed as i64,
457
732
                                RFBFrameType::Pdu as u8,
458
732
                            );
459
732
460
732
                            current = rem;
461
732
462
732
                            SCLogDebug!(
463
732
                                "supported_security_types: {}, types: {}",
464
732
                                request.number_of_types,
465
732
                                request
466
732
                                    .types
467
732
                                    .iter()
468
732
                                    .map(ToString::to_string)
469
732
                                    .map(|v| v + " ")
470
732
                                    .collect::<String>()
471
732
                            );
472
732
473
732
                            self.state = parser::RFBGlobalState::TSSecurityTypeSelection;
474
732
                            if request.number_of_types == 0 {
475
229
                                self.state = parser::RFBGlobalState::TCFailureReason;
476
503
                            }
477
478
732
                            if let Some(current_transaction) = self.get_current_tx() {
479
732
                                current_transaction.tc_supported_security_types = Some(request);
480
732
                            } else {
481
0
                                debug_validate_fail!("no transaction set at security type stage");
482
                            }
483
                        }
484
                        Err(Err::Incomplete(_)) => {
485
448
                            return AppLayerResult::incomplete(
486
448
                                consumed as u32,
487
448
                                (current.len() + 1) as u32,
488
448
                            );
489
                        }
490
                        Err(_) => {
491
0
                            if let Some(current_transaction) = self.get_current_tx() {
492
0
                                current_transaction.set_event(RFBEvent::MalformedMessage);
493
0
                                current_transaction.complete = true;
494
0
                            }
495
                            // Continue the flow but stop trying to map the protocol.
496
0
                            self.state = parser::RFBGlobalState::Skip;
497
0
                            return AppLayerResult::ok();
498
                        }
499
                    }
500
                }
501
                parser::RFBGlobalState::TCServerSecurityType => {
502
                    // In RFB 3.3, the server decides the authentication type
503
490
                    match parser::parse_server_security_type(current) {
504
167
                        Ok((rem, request)) => {
505
167
                            consumed += current.len() - rem.len();
506
167
                            let _pdu = Frame::new(
507
167
                                flow,
508
167
                                &stream_slice,
509
167
                                current,
510
167
                                consumed as i64,
511
167
                                RFBFrameType::Pdu as u8,
512
167
                            );
513
167
514
167
                            current = rem;
515
167
516
167
                            let chosen_security_type = request.security_type;
517
167
                            SCLogDebug!("chosen_security_type: {}", chosen_security_type);
518
167
                            match chosen_security_type {
519
22
                                0 => self.state = parser::RFBGlobalState::TCFailureReason,
520
0
                                1 => self.state = parser::RFBGlobalState::TSClientInit,
521
106
                                2 => self.state = parser::RFBGlobalState::TCVncChallenge,
522
                                _ => {
523
39
                                    if let Some(current_transaction) = self.get_current_tx() {
524
39
                                        current_transaction
525
39
                                            .set_event(RFBEvent::UnimplementedSecurityType);
526
39
                                        current_transaction.complete = true;
527
39
                                    } else {
528
0
                                        debug_validate_fail!(
529
0
                                            "no transaction set at security type stage"
530
                                        );
531
                                    }
532
                                    // We have just have seen a security type we don't know about.
533
                                    // This is not bad per se, it might just mean this is a
534
                                    // proprietary one not in the spec.
535
                                    // Continue the flow but stop trying to map the protocol.
536
39
                                    self.state = parser::RFBGlobalState::Skip;
537
39
                                    return AppLayerResult::ok();
538
                                }
539
                            }
540
541
128
                            if let Some(current_transaction) = self.get_current_tx() {
542
128
                                current_transaction.tc_server_security_type = Some(request);
543
128
                                current_transaction.chosen_security_type =
544
128
                                    Some(chosen_security_type);
545
128
                            } else {
546
0
                                debug_validate_fail!("no transaction set at security type stage");
547
                            }
548
                        }
549
                        Err(Err::Incomplete(_)) => {
550
323
                            return AppLayerResult::incomplete(
551
323
                                consumed as u32,
552
323
                                (current.len() + 1) as u32,
553
323
                            );
554
                        }
555
                        Err(_) => {
556
0
                            if let Some(current_transaction) = self.get_current_tx() {
557
0
                                current_transaction.set_event(RFBEvent::MalformedMessage);
558
0
                                current_transaction.complete = true;
559
0
                            }
560
                            // Continue the flow but stop trying to map the protocol.
561
0
                            self.state = parser::RFBGlobalState::Skip;
562
0
                            return AppLayerResult::ok();
563
                        }
564
                    }
565
                }
566
320
                parser::RFBGlobalState::TCVncChallenge => match parser::parse_vnc_auth(current) {
567
100
                    Ok((rem, request)) => {
568
100
                        consumed += current.len() - rem.len();
569
100
                        let _pdu = Frame::new(
570
100
                            flow,
571
100
                            &stream_slice,
572
100
                            current,
573
100
                            consumed as i64,
574
100
                            RFBFrameType::Pdu as u8,
575
100
                        );
576
100
577
100
                        current = rem;
578
100
579
100
                        self.state = parser::RFBGlobalState::TSVncResponse;
580
581
100
                        if let Some(current_transaction) = self.get_current_tx() {
582
100
                            current_transaction.tc_vnc_challenge = Some(request);
583
100
                        } else {
584
0
                            debug_validate_fail!("no transaction set at auth stage");
585
                        }
586
                    }
587
                    Err(Err::Incomplete(_)) => {
588
220
                        return AppLayerResult::incomplete(
589
220
                            consumed as u32,
590
220
                            (current.len() + 1) as u32,
591
220
                        );
592
                    }
593
                    Err(_) => {
594
0
                        if let Some(current_transaction) = self.get_current_tx() {
595
0
                            current_transaction.set_event(RFBEvent::MalformedMessage);
596
0
                            current_transaction.complete = true;
597
0
                        }
598
                        // Continue the flow but stop trying to map the protocol.
599
0
                        self.state = parser::RFBGlobalState::Skip;
600
0
                        return AppLayerResult::ok();
601
                    }
602
                },
603
                parser::RFBGlobalState::TCSecurityResult => {
604
247
                    match parser::parse_security_result(current) {
605
29
                        Ok((rem, request)) => {
606
29
                            consumed += current.len() - rem.len();
607
29
                            let _pdu = Frame::new(
608
29
                                flow,
609
29
                                &stream_slice,
610
29
                                current,
611
29
                                consumed as i64,
612
29
                                RFBFrameType::Pdu as u8,
613
29
                            );
614
29
615
29
                            current = rem;
616
29
617
29
                            if request.status == 0 {
618
16
                                self.state = parser::RFBGlobalState::TSClientInit;
619
620
16
                                if let Some(current_transaction) = self.get_current_tx() {
621
16
                                    current_transaction.tc_security_result = Some(request);
622
16
                                } else {
623
0
                                    debug_validate_fail!(
624
0
                                        "no transaction set at security result stage"
625
                                    );
626
                                }
627
13
                            } else if request.status == 1 {
628
7
                                self.state = parser::RFBGlobalState::TCFailureReason;
629
7
                            } else {
630
6
                                if let Some(current_transaction) = self.get_current_tx() {
631
6
                                    current_transaction.set_event(RFBEvent::UnknownSecurityResult);
632
6
                                    current_transaction.complete = true;
633
6
                                }
634
                                // Continue the flow but stop trying to map the protocol.
635
6
                                self.state = parser::RFBGlobalState::Skip;
636
6
                                return AppLayerResult::ok();
637
                            }
638
                        }
639
                        Err(Err::Incomplete(_)) => {
640
218
                            return AppLayerResult::incomplete(
641
218
                                consumed as u32,
642
218
                                (current.len() + 1) as u32,
643
218
                            );
644
                        }
645
                        Err(_) => {
646
0
                            if let Some(current_transaction) = self.get_current_tx() {
647
0
                                current_transaction.set_event(RFBEvent::MalformedMessage);
648
0
                                current_transaction.complete = true;
649
0
                            }
650
                            // Continue the flow but stop trying to map the protocol.
651
0
                            self.state = parser::RFBGlobalState::Skip;
652
0
                            return AppLayerResult::ok();
653
                        }
654
                    }
655
                }
656
                parser::RFBGlobalState::TCFailureReason => {
657
4.67k
                    match parser::parse_failure_reason(current) {
658
1.46k
                        Ok((_rem, request)) => {
659
1.46k
                            if let Some(current_transaction) = self.get_current_tx() {
660
1.46k
                                current_transaction.tc_failure_reason = Some(request);
661
1.46k
                            } else {
662
0
                                debug_validate_fail!("no transaction set at failure reason stage");
663
                            }
664
1.46k
                            return AppLayerResult::ok();
665
                        }
666
                        Err(Err::Incomplete(_)) => {
667
3.19k
                            return AppLayerResult::incomplete(
668
3.19k
                                consumed as u32,
669
3.19k
                                (current.len() + 1) as u32,
670
3.19k
                            );
671
                        }
672
                        Err(_) => {
673
16
                            if let Some(current_transaction) = self.get_current_tx() {
674
16
                                current_transaction.set_event(RFBEvent::MalformedMessage);
675
16
                                current_transaction.complete = true;
676
16
                            }
677
                            // Continue the flow but stop trying to map the protocol.
678
16
                            self.state = parser::RFBGlobalState::Skip;
679
16
                            return AppLayerResult::ok();
680
                        }
681
                    }
682
                }
683
                parser::RFBGlobalState::TCServerInit => {
684
3.37k
                    match parser::parse_server_init(current) {
685
196
                        Ok((rem, request)) => {
686
196
                            consumed += current.len() - rem.len();
687
196
                            let _pdu = Frame::new(
688
196
                                flow,
689
196
                                &stream_slice,
690
196
                                current,
691
196
                                consumed as i64,
692
196
                                RFBFrameType::Pdu as u8,
693
196
                            );
694
196
695
196
                            current = rem;
696
196
697
196
                            self.state = parser::RFBGlobalState::Skip;
698
699
196
                            if let Some(current_transaction) = self.get_current_tx() {
700
196
                                current_transaction.tc_server_init = Some(request);
701
196
                                // connection initialization is complete and parsed
702
196
                                current_transaction.complete = true;
703
196
                            } else {
704
0
                                debug_validate_fail!("no transaction set at server init stage");
705
                            }
706
                        }
707
                        Err(Err::Incomplete(_)) => {
708
3.18k
                            return AppLayerResult::incomplete(
709
3.18k
                                consumed as u32,
710
3.18k
                                (current.len() + 1) as u32,
711
3.18k
                            );
712
                        }
713
                        Err(_) => {
714
0
                            if let Some(current_transaction) = self.get_current_tx() {
715
0
                                current_transaction.set_event(RFBEvent::MalformedMessage);
716
0
                                current_transaction.complete = true;
717
0
                            }
718
                            // Continue the flow but stop trying to map the protocol.
719
0
                            self.state = parser::RFBGlobalState::Skip;
720
0
                            return AppLayerResult::ok();
721
                        }
722
                    }
723
                }
724
                parser::RFBGlobalState::Skip => {
725
                    //todo implement RFB messages, for now we stop here
726
2.13k
                    return AppLayerResult::ok();
727
                }
728
                _ => {
729
                    // We have gotten out of sync with the expected state flow.
730
                    // This could happen since we use a global state (i.e. that
731
                    // is used for both directions), but if traffic can not be
732
                    // parsed as expected elsewhere, we might not have advanced
733
                    // a state for one direction but received data in the
734
                    // "unexpected" direction, causing the parser to end up
735
                    // here. Let's stop trying to parse the traffic but still
736
                    // accept it.
737
                    SCLogDebug!("Invalid state for response: {}", self.state);
738
287
                    if let Some(current_transaction) = self.get_current_tx() {
739
287
                        current_transaction.set_event(RFBEvent::ConfusedState);
740
287
                        current_transaction.complete = true;
741
287
                    }
742
287
                    self.state = parser::RFBGlobalState::Skip;
743
287
                    return AppLayerResult::ok();
744
                }
745
            }
746
        }
747
15.1k
    }
748
}
749
750
// C exports.
751
752
#[no_mangle]
753
1.57k
pub extern "C" fn rs_rfb_state_new(
754
1.57k
    _orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto,
755
1.57k
) -> *mut std::os::raw::c_void {
756
1.57k
    let state = RFBState::new();
757
1.57k
    let boxed = Box::new(state);
758
1.57k
    return Box::into_raw(boxed) as *mut _;
759
1.57k
}
760
761
#[no_mangle]
762
1.57k
pub extern "C" fn rs_rfb_state_free(state: *mut std::os::raw::c_void) {
763
1.57k
    // Just unbox...
764
1.57k
    std::mem::drop(unsafe { Box::from_raw(state as *mut RFBState) });
765
1.57k
}
766
767
#[no_mangle]
768
44
pub unsafe extern "C" fn rs_rfb_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) {
769
44
    let state = cast_pointer!(state, RFBState);
770
44
    state.free_tx(tx_id);
771
44
}
772
773
#[no_mangle]
774
4.65k
pub unsafe extern "C" fn rs_rfb_parse_request(
775
4.65k
    flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
776
4.65k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
777
4.65k
) -> AppLayerResult {
778
4.65k
    let state = cast_pointer!(state, RFBState);
779
4.65k
    return state.parse_request(flow, stream_slice);
780
4.65k
}
781
782
#[no_mangle]
783
15.1k
pub unsafe extern "C" fn rs_rfb_parse_response(
784
15.1k
    flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
785
15.1k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
786
15.1k
) -> AppLayerResult {
787
15.1k
    let state = cast_pointer!(state, RFBState);
788
15.1k
    return state.parse_response(flow, stream_slice);
789
15.1k
}
790
791
#[no_mangle]
792
18
pub unsafe extern "C" fn rs_rfb_state_get_tx(
793
18
    state: *mut std::os::raw::c_void, tx_id: u64,
794
18
) -> *mut std::os::raw::c_void {
795
18
    let state = cast_pointer!(state, RFBState);
796
18
    match state.get_tx(tx_id) {
797
0
        Some(tx) => {
798
0
            return tx as *const _ as *mut _;
799
        }
800
        None => {
801
18
            return std::ptr::null_mut();
802
        }
803
    }
804
18
}
805
806
#[no_mangle]
807
59.9k
pub unsafe extern "C" fn rs_rfb_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 {
808
59.9k
    let state = cast_pointer!(state, RFBState);
809
59.9k
    return state.tx_id;
810
59.9k
}
811
812
#[no_mangle]
813
12.5k
pub unsafe extern "C" fn rs_rfb_tx_get_alstate_progress(
814
12.5k
    tx: *mut std::os::raw::c_void, _direction: u8,
815
12.5k
) -> std::os::raw::c_int {
816
12.5k
    let tx = cast_pointer!(tx, RFBTransaction);
817
12.5k
    if tx.complete {
818
126
        return 1;
819
12.4k
    }
820
12.4k
    return 0;
821
12.5k
}
822
823
// Parser name as a C style string.
824
const PARSER_NAME: &[u8] = b"rfb\0";
825
826
export_tx_data_get!(rs_rfb_get_tx_data, RFBTransaction);
827
export_state_data_get!(rs_rfb_get_state_data, RFBState);
828
829
#[no_mangle]
830
34
pub unsafe extern "C" fn rs_rfb_register_parser() {
831
34
    let parser = RustParser {
832
34
        name: PARSER_NAME.as_ptr() as *const std::os::raw::c_char,
833
34
        default_port: std::ptr::null(),
834
34
        ipproto: IPPROTO_TCP,
835
34
        probe_ts: None,
836
34
        probe_tc: None,
837
34
        min_depth: 0,
838
34
        max_depth: 16,
839
34
        state_new: rs_rfb_state_new,
840
34
        state_free: rs_rfb_state_free,
841
34
        tx_free: rs_rfb_state_tx_free,
842
34
        parse_ts: rs_rfb_parse_request,
843
34
        parse_tc: rs_rfb_parse_response,
844
34
        get_tx_count: rs_rfb_state_get_tx_count,
845
34
        get_tx: rs_rfb_state_get_tx,
846
34
        tx_comp_st_ts: 1,
847
34
        tx_comp_st_tc: 1,
848
34
        tx_get_progress: rs_rfb_tx_get_alstate_progress,
849
34
        get_eventinfo: Some(RFBEvent::get_event_info),
850
34
        get_eventinfo_byid: Some(RFBEvent::get_event_info_by_id),
851
34
        localstorage_new: None,
852
34
        localstorage_free: None,
853
34
        get_tx_files: None,
854
34
        get_tx_iterator: Some(applayer::state_get_tx_iterator::<RFBState, RFBTransaction>),
855
34
        get_tx_data: rs_rfb_get_tx_data,
856
34
        get_state_data: rs_rfb_get_state_data,
857
34
        apply_tx_config: None,
858
34
        flags: 0,
859
34
        truncate: None,
860
34
        get_frame_id_by_name: Some(RFBFrameType::ffi_id_from_name),
861
34
        get_frame_name_by_id: Some(RFBFrameType::ffi_name_from_id),
862
34
    };
863
34
864
34
    let ip_proto_str = CString::new("tcp").unwrap();
865
34
866
34
    if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
867
34
        let alproto = AppLayerRegisterProtocolDetection(&parser, 1);
868
34
        ALPROTO_RFB = alproto;
869
34
        if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
870
34
            let _ = AppLayerRegisterParser(&parser, alproto);
871
34
        }
872
        SCLogDebug!("Rust rfb parser registered.");
873
0
    } else {
874
0
        SCLogDebug!("Protocol detector and parser disabled for RFB.");
875
0
    }
876
34
}
877
878
#[cfg(test)]
879
mod test {
880
    use super::*;
881
    use crate::core::STREAM_START;
882
883
    #[test]
884
    fn test_error_state() {
885
        let mut state = RFBState::new();
886
887
        let buf: &[u8] = &[
888
            0x05, 0x00, 0x03, 0x20, 0x20, 0x18, 0x00, 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
889
            0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x61, 0x6e, 0x65, 0x61,
890
            0x67, 0x6c, 0x65, 0x73, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
891
            0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
892
        ];
893
        let r = state.parse_response(
894
            std::ptr::null(),
895
            StreamSlice::from_slice(buf, STREAM_START, 0),
896
        );
897
898
        assert_eq!(
899
            r,
900
            AppLayerResult {
901
                status: -1,
902
                consumed: 0,
903
                needed: 0
904
            }
905
        );
906
    }
907
908
    // Test the state machine for RFB protocol
909
    // Passes an initial buffer with initial RFBState = TCServerProtocolVersion
910
    // Tests various client and server RFBStates as the buffer is parsed using parse_request and parse_response functions
911
    #[test]
912
    fn test_rfb_state_machine() {
913
        let mut init_state = RFBState::new();
914
915
        let buf: &[u8] = &[
916
            0x52, 0x46, 0x42, 0x20, 0x30, 0x30, 0x33, 0x2e, 0x30, 0x30, 0x38, 0x0a,
917
            0x01, /* Number of security types: 1 */
918
            0x02, /* Security type: VNC (2) */
919
            0x02, /* Security type selected: VNC (2) */
920
            0x54, 0x7b, 0x7a, 0x6f, 0x36, 0xa1, 0x54, 0xdb, 0x03, 0xa2, 0x57, 0x5c, 0x6f, 0x2a,
921
            0x4e,
922
            0xc5, /* 16 byte Authentication challenge: 547b7a6f36a154db03a2575c6f2a4ec5 */
923
            0x00, 0x00, 0x00, 0x00, /* Authentication result: OK */
924
            0x00, /* Share desktop flag: False */
925
            0x05, 0x00, 0x03, 0x20, 0x20, 0x18, 0x00, 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
926
            0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x61, 0x6e, 0x65, 0x61,
927
            0x67, 0x6c, 0x65, 0x73, 0x40, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
928
            0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69,
929
            0x6e, /* Server framebuffer parameters */
930
        ];
931
932
        //The buffer values correspond to Server Protocol version: 003.008
933
        // Same buffer is used for both functions due to similar values in request and response
934
        init_state.parse_response(
935
            std::ptr::null(),
936
            StreamSlice::from_slice(&buf[0..12], STREAM_START, 0),
937
        );
938
        let mut ok_state = parser::RFBGlobalState::TSClientProtocolVersion;
939
        assert_eq!(init_state.state, ok_state);
940
941
        //The buffer values correspond to Client Protocol version: 003.008
942
        init_state.parse_request(
943
            std::ptr::null(),
944
            StreamSlice::from_slice(&buf[0..12], STREAM_START, 0),
945
        );
946
        ok_state = parser::RFBGlobalState::TCSupportedSecurityTypes;
947
        assert_eq!(init_state.state, ok_state);
948
949
        init_state.parse_response(
950
            std::ptr::null(),
951
            StreamSlice::from_slice(&buf[12..14], STREAM_START, 0),
952
        );
953
        ok_state = parser::RFBGlobalState::TSSecurityTypeSelection;
954
        assert_eq!(init_state.state, ok_state);
955
956
        init_state.parse_request(
957
            std::ptr::null(),
958
            StreamSlice::from_slice(&buf[14..15], STREAM_START, 0),
959
        );
960
        ok_state = parser::RFBGlobalState::TCVncChallenge;
961
        assert_eq!(init_state.state, ok_state);
962
963
        //The buffer values correspond to Server Authentication challenge: 547b7a6f36a154db03a2575c6f2a4ec5
964
        // Same buffer is used for both functions due to similar values in request and response
965
        init_state.parse_response(
966
            std::ptr::null(),
967
            StreamSlice::from_slice(&buf[15..31], STREAM_START, 0),
968
        );
969
        ok_state = parser::RFBGlobalState::TSVncResponse;
970
        assert_eq!(init_state.state, ok_state);
971
972
        //The buffer values correspond to Client Authentication response: 547b7a6f36a154db03a2575c6f2a4ec5
973
        init_state.parse_request(
974
            std::ptr::null(),
975
            StreamSlice::from_slice(&buf[15..31], STREAM_START, 0),
976
        );
977
        ok_state = parser::RFBGlobalState::TCSecurityResult;
978
        assert_eq!(init_state.state, ok_state);
979
980
        init_state.parse_response(
981
            std::ptr::null(),
982
            StreamSlice::from_slice(&buf[31..35], STREAM_START, 0),
983
        );
984
        ok_state = parser::RFBGlobalState::TSClientInit;
985
        assert_eq!(init_state.state, ok_state);
986
987
        init_state.parse_request(
988
            std::ptr::null(),
989
            StreamSlice::from_slice(&buf[35..36], STREAM_START, 0),
990
        );
991
        ok_state = parser::RFBGlobalState::TCServerInit;
992
        assert_eq!(init_state.state, ok_state);
993
994
        init_state.parse_response(
995
            std::ptr::null(),
996
            StreamSlice::from_slice(&buf[36..90], STREAM_START, 0),
997
        );
998
        ok_state = parser::RFBGlobalState::Skip;
999
        assert_eq!(init_state.state, ok_state);
1000
    }
1001
}