Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/rust/src/rfb/rfb.rs
Line
Count
Source
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
#[derive(FromPrimitive, Debug, AppLayerEvent)]
33
pub enum RFBEvent {
34
    UnimplementedSecurityType,
35
    UnknownSecurityResult,
36
    MalformedMessage,
37
    ConfusedState,
38
}
39
40
#[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
198k
    fn id(&self) -> u64 {
66
198k
        self.tx_id
67
198k
    }
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.35k
    pub fn new() -> Self {
78
1.35k
        Self {
79
1.35k
            tx_id: 0,
80
1.35k
            complete: false,
81
1.35k
            chosen_security_type: None,
82
1.35k
83
1.35k
            tc_server_protocol_version: None,
84
1.35k
            ts_client_protocol_version: None,
85
1.35k
            tc_supported_security_types: None,
86
1.35k
            ts_security_type_selection: None,
87
1.35k
            tc_server_security_type: None,
88
1.35k
            tc_vnc_challenge: None,
89
1.35k
            ts_vnc_response: None,
90
1.35k
            ts_client_init: None,
91
1.35k
            tc_security_result: None,
92
1.35k
            tc_failure_reason: None,
93
1.35k
            tc_server_init: None,
94
1.35k
95
1.35k
            tx_data: applayer::AppLayerTxData::new(),
96
1.35k
        }
97
1.35k
    }
98
99
424
    fn set_event(&mut self, event: RFBEvent) {
100
424
        self.tx_data.set_event(event as u8);
101
424
    }
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
146k
    fn get_transaction_count(&self) -> usize {
113
146k
        self.transactions.len()
114
146k
    }
115
116
99.4k
    fn get_transaction_by_index(&self, index: usize) -> Option<&RFBTransaction> {
117
99.4k
        self.transactions.get(index)
118
99.4k
    }
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.71k
    pub fn new() -> Self {
129
1.71k
        Self {
130
1.71k
            state_data: AppLayerStateData::new(),
131
1.71k
            tx_id: 0,
132
1.71k
            transactions: Vec::new(),
133
1.71k
            state: parser::RFBGlobalState::TCServerProtocolVersion,
134
1.71k
        }
135
1.71k
    }
136
137
    // Free a transaction by ID.
138
113
    fn free_tx(&mut self, tx_id: u64) {
139
113
        let len = self.transactions.len();
140
113
        let mut found = false;
141
113
        let mut index = 0;
142
113
        for i in 0..len {
143
113
            let tx = &self.transactions[i];
144
113
            if tx.tx_id == tx_id + 1 {
145
113
                found = true;
146
113
                index = i;
147
113
                break;
148
0
            }
149
        }
150
113
        if found {
151
113
            self.transactions.remove(index);
152
113
        }
153
113
    }
154
155
46
    pub fn get_tx(&mut self, tx_id: u64) -> Option<&RFBTransaction> {
156
46
        self.transactions.iter().find(|tx| tx.tx_id == tx_id + 1)
157
46
    }
158
159
1.35k
    fn new_tx(&mut self) -> RFBTransaction {
160
1.35k
        let mut tx = RFBTransaction::new();
161
1.35k
        self.tx_id += 1;
162
1.35k
        tx.tx_id = self.tx_id;
163
1.35k
        return tx;
164
1.35k
    }
165
166
8.07k
    fn get_current_tx(&mut self) -> Option<&mut RFBTransaction> {
167
8.07k
        let tx_id = self.tx_id;
168
8.07k
        let r = self.transactions.iter_mut().find(|tx| tx.tx_id == tx_id);
169
8.07k
        if let Some(tx) = r {
170
7.91k
            tx.tx_data.updated_tc = true;
171
7.91k
            tx.tx_data.updated_ts = true;
172
7.91k
            return Some(tx);
173
158
        }
174
158
        return None;
175
8.07k
    }
176
177
23.4k
    fn parse_request(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> AppLayerResult {
178
23.4k
        let input = stream_slice.as_slice();
179
180
        // We're not interested in empty requests.
181
23.4k
        if input.is_empty() {
182
12
            return AppLayerResult::ok();
183
23.4k
        }
184
185
23.4k
        let mut current = input;
186
23.4k
        let mut consumed = 0;
187
        SCLogDebug!("request_state {}, input_len {}", self.state, input.len());
188
        loop {
189
25.7k
            if current.is_empty() {
190
1.74k
                return AppLayerResult::ok();
191
24.0k
            }
192
24.0k
            match self.state {
193
                parser::RFBGlobalState::TSClientProtocolVersion => {
194
1.69k
                    match parser::parse_protocol_version(current) {
195
1.15k
                        Ok((rem, request)) => {
196
1.15k
                            consumed += current.len() - rem.len();
197
1.15k
                            let _pdu = Frame::new(
198
1.15k
                                flow,
199
1.15k
                                &stream_slice,
200
1.15k
                                current,
201
1.15k
                                consumed as i64,
202
1.15k
                                RFBFrameType::Pdu as u8,
203
                            );
204
205
1.15k
                            current = rem;
206
207
1.15k
                            if request.major == "003" && request.minor == "003" {
208
213
                                // in version 3.3 the server decided security type
209
213
                                self.state = parser::RFBGlobalState::TCServerSecurityType;
210
939
                            } else {
211
939
                                self.state = parser::RFBGlobalState::TCSupportedSecurityTypes;
212
939
                            }
213
214
1.15k
                            if let Some(current_transaction) = self.get_current_tx() {
215
1.15k
                                current_transaction.ts_client_protocol_version = Some(request);
216
1.15k
                            } else {
217
0
                                debug_validate_fail!(
218
0
                                    "no transaction set at protocol selection stage"
219
                                );
220
                            }
221
                        }
222
                        Err(Err::Incomplete(_)) => {
223
536
                            return AppLayerResult::incomplete(
224
536
                                consumed as u32,
225
536
                                (current.len() + 1) as u32,
226
                            );
227
                        }
228
                        Err(_) => {
229
                            // We even failed to parse the protocol version.
230
8
                            return AppLayerResult::err();
231
                        }
232
                    }
233
                }
234
                parser::RFBGlobalState::TSSecurityTypeSelection => {
235
558
                    match parser::parse_security_type_selection(current) {
236
558
                        Ok((rem, request)) => {
237
558
                            consumed += current.len() - rem.len();
238
558
                            let _pdu = Frame::new(
239
558
                                flow,
240
558
                                &stream_slice,
241
558
                                current,
242
558
                                consumed as i64,
243
558
                                RFBFrameType::Pdu as u8,
244
                            );
245
246
558
                            current = rem;
247
248
558
                            let chosen_security_type = request.security_type;
249
250
558
                            if let Some(current_transaction) = self.get_current_tx() {
251
558
                                current_transaction.ts_security_type_selection = Some(request);
252
558
                                current_transaction.chosen_security_type =
253
558
                                    Some(chosen_security_type as u32);
254
558
                            } else {
255
0
                                debug_validate_fail!("no transaction set at security type stage");
256
                            }
257
258
558
                            match chosen_security_type {
259
21
                                2 => self.state = parser::RFBGlobalState::TCVncChallenge,
260
522
                                1 => self.state = parser::RFBGlobalState::TSClientInit,
261
                                _ => {
262
15
                                    if let Some(current_transaction) = self.get_current_tx() {
263
15
                                        current_transaction
264
15
                                            .set_event(RFBEvent::UnimplementedSecurityType);
265
15
                                    }
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
15
                                    self.state = parser::RFBGlobalState::Skip;
271
15
                                    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
                            );
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
310
                parser::RFBGlobalState::TSVncResponse => match parser::parse_vnc_auth(current) {
294
85
                    Ok((rem, request)) => {
295
85
                        consumed += current.len() - rem.len();
296
85
                        let _pdu = Frame::new(
297
85
                            flow,
298
85
                            &stream_slice,
299
85
                            current,
300
85
                            consumed as i64,
301
85
                            RFBFrameType::Pdu as u8,
302
                        );
303
304
85
                        current = rem;
305
306
85
                        self.state = parser::RFBGlobalState::TCSecurityResult;
307
308
85
                        if let Some(current_transaction) = self.get_current_tx() {
309
85
                            current_transaction.ts_vnc_response = Some(request);
310
85
                        } else {
311
0
                            debug_validate_fail!("no transaction set at security result stage");
312
                        }
313
                    }
314
                    Err(Err::Incomplete(_)) => {
315
225
                        return AppLayerResult::incomplete(
316
225
                            consumed as u32,
317
225
                            (current.len() + 1) as u32,
318
                        );
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
538
                parser::RFBGlobalState::TSClientInit => match parser::parse_client_init(current) {
331
538
                    Ok((rem, request)) => {
332
538
                        consumed += current.len() - rem.len();
333
538
                        let _pdu = Frame::new(
334
538
                            flow,
335
538
                            &stream_slice,
336
538
                            current,
337
538
                            consumed as i64,
338
538
                            RFBFrameType::Pdu as u8,
339
                        );
340
341
538
                        current = rem;
342
343
538
                        self.state = parser::RFBGlobalState::TCServerInit;
344
345
538
                        if let Some(current_transaction) = self.get_current_tx() {
346
538
                            current_transaction.ts_client_init = Some(request);
347
538
                        } 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
                        );
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
20.6k
                    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
281
                    if let Some(current_transaction) = self.get_current_tx() {
383
123
                        current_transaction.set_event(RFBEvent::ConfusedState);
384
123
                        current_transaction.complete = true;
385
158
                    }
386
281
                    self.state = parser::RFBGlobalState::Skip;
387
281
                    return AppLayerResult::ok();
388
                }
389
            }
390
        }
391
23.4k
    }
392
393
121k
    fn parse_response(&mut self, flow: *const Flow, stream_slice: StreamSlice) -> AppLayerResult {
394
121k
        let input = stream_slice.as_slice();
395
        // We're not interested in empty responses.
396
121k
        if input.is_empty() {
397
9
            return AppLayerResult::ok();
398
121k
        }
399
400
121k
        let mut current = input;
401
121k
        let mut consumed = 0;
402
        SCLogDebug!(
403
            "response_state {}, response_len {}",
404
            self.state,
405
            input.len()
406
        );
407
        loop {
408
124k
            if current.is_empty() {
409
1.97k
                return AppLayerResult::ok();
410
122k
            }
411
122k
            match self.state {
412
                parser::RFBGlobalState::TCServerProtocolVersion => {
413
3.51k
                    match parser::parse_protocol_version(current) {
414
1.35k
                        Ok((rem, request)) => {
415
1.35k
                            consumed += current.len() - rem.len();
416
1.35k
                            let _pdu = Frame::new(
417
1.35k
                                flow,
418
1.35k
                                &stream_slice,
419
1.35k
                                current,
420
1.35k
                                consumed as i64,
421
1.35k
                                RFBFrameType::Pdu as u8,
422
                            );
423
424
1.35k
                            current = rem;
425
426
1.35k
                            self.state = parser::RFBGlobalState::TSClientProtocolVersion;
427
1.35k
                            let tx = self.new_tx();
428
1.35k
                            self.transactions.push(tx);
429
430
1.35k
                            if let Some(current_transaction) = self.get_current_tx() {
431
1.35k
                                current_transaction.tc_server_protocol_version = Some(request);
432
1.35k
                            } else {
433
0
                                debug_validate_fail!("no transaction set but we just set one");
434
                            }
435
                        }
436
                        Err(Err::Incomplete(_)) => {
437
2.04k
                            return AppLayerResult::incomplete(
438
2.04k
                                consumed as u32,
439
2.04k
                                (current.len() + 1) as u32,
440
                            );
441
                        }
442
                        Err(_) => {
443
                            // We even failed to parse the protocol version.
444
112
                            return AppLayerResult::err();
445
                        }
446
                    }
447
                }
448
                parser::RFBGlobalState::TCSupportedSecurityTypes => {
449
3.92k
                    match parser::parse_supported_security_types(current) {
450
821
                        Ok((rem, request)) => {
451
821
                            consumed += current.len() - rem.len();
452
821
                            let _pdu = Frame::new(
453
821
                                flow,
454
821
                                &stream_slice,
455
821
                                current,
456
821
                                consumed as i64,
457
821
                                RFBFrameType::Pdu as u8,
458
                            );
459
460
821
                            current = rem;
461
462
                            SCLogDebug!(
463
                                "supported_security_types: {}, types: {}",
464
                                request.number_of_types,
465
                                request
466
                                    .types
467
                                    .iter()
468
                                    .map(ToString::to_string)
469
                                    .map(|v| v + " ")
470
                                    .collect::<String>()
471
                            );
472
473
821
                            self.state = parser::RFBGlobalState::TSSecurityTypeSelection;
474
821
                            if request.number_of_types == 0 {
475
231
                                self.state = parser::RFBGlobalState::TCFailureReason;
476
590
                            }
477
478
821
                            if let Some(current_transaction) = self.get_current_tx() {
479
821
                                current_transaction.tc_supported_security_types = Some(request);
480
821
                            } else {
481
0
                                debug_validate_fail!("no transaction set at security type stage");
482
                            }
483
                        }
484
                        Err(Err::Incomplete(_)) => {
485
3.10k
                            return AppLayerResult::incomplete(
486
3.10k
                                consumed as u32,
487
3.10k
                                (current.len() + 1) as u32,
488
                            );
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
518
                    match parser::parse_server_security_type(current) {
504
195
                        Ok((rem, request)) => {
505
195
                            consumed += current.len() - rem.len();
506
195
                            let _pdu = Frame::new(
507
195
                                flow,
508
195
                                &stream_slice,
509
195
                                current,
510
195
                                consumed as i64,
511
195
                                RFBFrameType::Pdu as u8,
512
                            );
513
514
195
                            current = rem;
515
516
195
                            let chosen_security_type = request.security_type;
517
                            SCLogDebug!("chosen_security_type: {}", chosen_security_type);
518
195
                            match chosen_security_type {
519
24
                                0 => self.state = parser::RFBGlobalState::TCFailureReason,
520
0
                                1 => self.state = parser::RFBGlobalState::TSClientInit,
521
135
                                2 => self.state = parser::RFBGlobalState::TCVncChallenge,
522
                                _ => {
523
36
                                    if let Some(current_transaction) = self.get_current_tx() {
524
36
                                        current_transaction
525
36
                                            .set_event(RFBEvent::UnimplementedSecurityType);
526
36
                                        current_transaction.complete = true;
527
36
                                    } 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
36
                                    self.state = parser::RFBGlobalState::Skip;
537
36
                                    return AppLayerResult::ok();
538
                                }
539
                            }
540
541
159
                            if let Some(current_transaction) = self.get_current_tx() {
542
159
                                current_transaction.tc_server_security_type = Some(request);
543
159
                                current_transaction.chosen_security_type =
544
159
                                    Some(chosen_security_type);
545
159
                            } 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
                            );
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
342
                parser::RFBGlobalState::TCVncChallenge => match parser::parse_vnc_auth(current) {
567
140
                    Ok((rem, request)) => {
568
140
                        consumed += current.len() - rem.len();
569
140
                        let _pdu = Frame::new(
570
140
                            flow,
571
140
                            &stream_slice,
572
140
                            current,
573
140
                            consumed as i64,
574
140
                            RFBFrameType::Pdu as u8,
575
                        );
576
577
140
                        current = rem;
578
579
140
                        self.state = parser::RFBGlobalState::TSVncResponse;
580
581
140
                        if let Some(current_transaction) = self.get_current_tx() {
582
140
                            current_transaction.tc_vnc_challenge = Some(request);
583
140
                        } else {
584
0
                            debug_validate_fail!("no transaction set at auth stage");
585
                        }
586
                    }
587
                    Err(Err::Incomplete(_)) => {
588
202
                        return AppLayerResult::incomplete(
589
202
                            consumed as u32,
590
202
                            (current.len() + 1) as u32,
591
                        );
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
240
                    match parser::parse_security_result(current) {
605
45
                        Ok((rem, request)) => {
606
45
                            consumed += current.len() - rem.len();
607
45
                            let _pdu = Frame::new(
608
45
                                flow,
609
45
                                &stream_slice,
610
45
                                current,
611
45
                                consumed as i64,
612
45
                                RFBFrameType::Pdu as u8,
613
                            );
614
615
45
                            current = rem;
616
617
45
                            if request.status == 0 {
618
23
                                self.state = parser::RFBGlobalState::TSClientInit;
619
620
23
                                if let Some(current_transaction) = self.get_current_tx() {
621
23
                                    current_transaction.tc_security_result = Some(request);
622
23
                                } else {
623
0
                                    debug_validate_fail!(
624
0
                                        "no transaction set at security result stage"
625
                                    );
626
                                }
627
22
                            } else if request.status == 1 {
628
12
                                self.state = parser::RFBGlobalState::TCFailureReason;
629
12
                            } else {
630
10
                                if let Some(current_transaction) = self.get_current_tx() {
631
10
                                    current_transaction.set_event(RFBEvent::UnknownSecurityResult);
632
10
                                    current_transaction.complete = true;
633
10
                                }
634
                                // Continue the flow but stop trying to map the protocol.
635
10
                                self.state = parser::RFBGlobalState::Skip;
636
10
                                return AppLayerResult::ok();
637
                            }
638
                        }
639
                        Err(Err::Incomplete(_)) => {
640
195
                            return AppLayerResult::incomplete(
641
195
                                consumed as u32,
642
195
                                (current.len() + 1) as u32,
643
                            );
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
14.6k
                    match parser::parse_failure_reason(current) {
658
2.43k
                        Ok((_rem, request)) => {
659
2.43k
                            if let Some(current_transaction) = self.get_current_tx() {
660
2.43k
                                current_transaction.tc_failure_reason = Some(request);
661
2.43k
                            } else {
662
0
                                debug_validate_fail!("no transaction set at failure reason stage");
663
                            }
664
2.43k
                            return AppLayerResult::ok();
665
                        }
666
                        Err(Err::Incomplete(_)) => {
667
12.2k
                            return AppLayerResult::incomplete(
668
12.2k
                                consumed as u32,
669
12.2k
                                (current.len() + 1) as u32,
670
                            );
671
                        }
672
                        Err(_) => {
673
26
                            if let Some(current_transaction) = self.get_current_tx() {
674
26
                                current_transaction.set_event(RFBEvent::MalformedMessage);
675
26
                                current_transaction.complete = true;
676
26
                            }
677
                            // Continue the flow but stop trying to map the protocol.
678
26
                            self.state = parser::RFBGlobalState::Skip;
679
26
                            return AppLayerResult::ok();
680
                        }
681
                    }
682
                }
683
                parser::RFBGlobalState::TCServerInit => {
684
76.3k
                    match parser::parse_server_init(current) {
685
218
                        Ok((rem, request)) => {
686
218
                            consumed += current.len() - rem.len();
687
218
                            let _pdu = Frame::new(
688
218
                                flow,
689
218
                                &stream_slice,
690
218
                                current,
691
218
                                consumed as i64,
692
218
                                RFBFrameType::Pdu as u8,
693
                            );
694
695
218
                            current = rem;
696
697
218
                            self.state = parser::RFBGlobalState::Skip;
698
699
218
                            if let Some(current_transaction) = self.get_current_tx() {
700
218
                                current_transaction.tc_server_init = Some(request);
701
218
                                // connection initialization is complete and parsed
702
218
                                current_transaction.complete = true;
703
218
                            } else {
704
0
                                debug_validate_fail!("no transaction set at server init stage");
705
                            }
706
                        }
707
                        Err(Err::Incomplete(_)) => {
708
76.1k
                            return AppLayerResult::incomplete(
709
76.1k
                                consumed as u32,
710
76.1k
                                (current.len() + 1) as u32,
711
                            );
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
22.7k
                    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
214
                    if let Some(current_transaction) = self.get_current_tx() {
739
214
                        current_transaction.set_event(RFBEvent::ConfusedState);
740
214
                        current_transaction.complete = true;
741
214
                    }
742
214
                    self.state = parser::RFBGlobalState::Skip;
743
214
                    return AppLayerResult::ok();
744
                }
745
            }
746
        }
747
121k
    }
748
}
749
750
// C exports.
751
752
#[no_mangle]
753
1.71k
pub extern "C" fn rs_rfb_state_new(
754
1.71k
    _orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto,
755
1.71k
) -> *mut std::os::raw::c_void {
756
1.71k
    let state = RFBState::new();
757
1.71k
    let boxed = Box::new(state);
758
1.71k
    return Box::into_raw(boxed) as *mut _;
759
1.71k
}
760
761
#[no_mangle]
762
1.71k
pub extern "C" fn rs_rfb_state_free(state: *mut std::os::raw::c_void) {
763
    // Just unbox...
764
1.71k
    std::mem::drop(unsafe { Box::from_raw(state as *mut RFBState) });
765
1.71k
}
766
767
#[no_mangle]
768
113
pub unsafe extern "C" fn rs_rfb_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) {
769
113
    let state = cast_pointer!(state, RFBState);
770
113
    state.free_tx(tx_id);
771
113
}
772
773
#[no_mangle]
774
23.4k
pub unsafe extern "C" fn rs_rfb_parse_request(
775
23.4k
    flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
776
23.4k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
777
23.4k
) -> AppLayerResult {
778
23.4k
    let state = cast_pointer!(state, RFBState);
779
23.4k
    return state.parse_request(flow, stream_slice);
780
23.4k
}
781
782
#[no_mangle]
783
121k
pub unsafe extern "C" fn rs_rfb_parse_response(
784
121k
    flow: *const Flow, state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void,
785
121k
    stream_slice: StreamSlice, _data: *const std::os::raw::c_void,
786
121k
) -> AppLayerResult {
787
121k
    let state = cast_pointer!(state, RFBState);
788
121k
    return state.parse_response(flow, stream_slice);
789
121k
}
790
791
#[no_mangle]
792
46
pub unsafe extern "C" fn rs_rfb_state_get_tx(
793
46
    state: *mut std::os::raw::c_void, tx_id: u64,
794
46
) -> *mut std::os::raw::c_void {
795
46
    let state = cast_pointer!(state, RFBState);
796
46
    match state.get_tx(tx_id) {
797
14
        Some(tx) => {
798
14
            return tx as *const _ as *mut _;
799
        }
800
        None => {
801
32
            return std::ptr::null_mut();
802
        }
803
    }
804
46
}
805
806
#[no_mangle]
807
437k
pub unsafe extern "C" fn rs_rfb_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 {
808
437k
    let state = cast_pointer!(state, RFBState);
809
437k
    return state.tx_id;
810
437k
}
811
812
#[no_mangle]
813
99.8k
pub unsafe extern "C" fn rs_rfb_tx_get_alstate_progress(
814
99.8k
    tx: *mut std::os::raw::c_void, _direction: u8,
815
99.8k
) -> std::os::raw::c_int {
816
99.8k
    let tx = cast_pointer!(tx, RFBTransaction);
817
99.8k
    if tx.complete {
818
401
        return 1;
819
99.4k
    }
820
99.4k
    return 0;
821
99.8k
}
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
864
34
    let ip_proto_str = CString::new("tcp").unwrap();
865
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
}