GithubHelp home page GithubHelp logo

devolutions / ironrdp Goto Github PK

View Code? Open in Web Editor NEW
314.0 24.0 41.0 11.75 MB

Rust implementation of the Microsoft Remote Desktop Protocol (RDP)

License: Apache License 2.0

Rust 89.04% JavaScript 0.08% HTML 0.06% TypeScript 1.45% CSS 0.20% Svelte 0.99% GLSL 0.22% PowerShell 0.01% C# 7.93%
rdp rust architecture

ironrdp's Introduction

IronRDP

A collection of Rust crates providing an implementation of the Microsoft Remote Desktop Protocol, with a focus on security.

Demonstration

ironrdp-tauri-client-hackaton-result.mp4

Video Codec Support

Supported codecs:

  • Uncompressed raw bitmap
  • Interleaved Run-Length Encoding (RLE) Bitmap Codec
  • RDP 6.0 Bitmap Compression
  • Microsoft RemoteFX (RFX)

Examples

A full-fledged RDP client based on IronRDP crates suite, and implemented using non-blocking, asynchronous I/O.

cargo run --bin ironrdp-client -- <HOSTNAME> --username <USERNAME> --password <PASSWORD>

Example of utilizing IronRDP in a blocking, synchronous fashion.

This example showcases the use of IronRDP in a blocking manner. It demonstrates how to create a basic RDP client with just a few hundred lines of code by leveraging the IronRDP crates suite.

In this basic client implementation, the client establishes a connection with the destination server, decodes incoming graphics updates, and saves the resulting output as a BMP image file on the disk.

cargo run --example=screenshot -- --host <HOSTNAME> --username <USERNAME> --password <PASSWORD> --output out.bmp

How to enable RemoteFX on server

Run the following PowerShell commands, and reboot.

Set-ItemProperty -Path 'HKLM:\Software\Policies\Microsoft\Windows NT\Terminal Services' -Name 'ColorDepth' -Type DWORD -Value 5
Set-ItemProperty -Path 'HKLM:\Software\Policies\Microsoft\Windows NT\Terminal Services' -Name 'fEnableVirtualizedGraphics' -Type DWORD -Value 1

Alternatively, you may change a few group policies using gpedit.msc:

  1. Run gpedit.msc.

  2. Enable Computer Configuration/Administrative Templates/Windows Components/Remote Desktop Services/Remote Desktop Session Host/Remote Session Environment/RemoteFX for Windows Server 2008 R2/Configure RemoteFX

  3. Enable Computer Configuration/Administrative Templates/Windows Components/Remote Desktop Services/Remote Desktop Session Host/Remote Session Environment/Enable RemoteFX encoding for RemoteFX clients designed for Windows Server 2008 R2 SP1

  4. Enable Computer Configuration/Administrative Templates/Windows Components/Remote Desktop Services/Remote Desktop Session Host/Remote Session Environment/Limit maximum color depth

  5. Reboot.

Architecture

See the ARCHITECTURE.md document.

Getting help

ironrdp's People

Contributors

awakecoding avatar cbenoit avatar dependabot[bot] avatar devolutionsbot avatar devolutionsinfra avatar dheater avatar ekse avatar elmarco avatar failshell avatar fotosmile avatar ibeckermayer avatar irvingoujatdevolution avatar mihneabuz avatar msabansal avatar ngirot-devolutions avatar nszetei avatar pacmancoder avatar probakowski avatar rrradicaledward avatar sandeepbansal avatar sduquette-devolutions avatar thenextman avatar vaffeine avatar zachariaellaham avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ironrdp's Issues

Panic in PreconnectionPdu::from_buffer

A panic was found by fuzzing PreconnectionPdu::from_buffer.

Test case: minimized-from-28e574a2945e691cffc674ed7d6319d255d3f275.zip
Branch: https://github.com/Devolutions/IronRDP/tree/fuzz-preconnection-pdu

cargo +nightly fuzz run fuzz_pdu minimized-from-28e574a2945e691cffc674ed7d6319d255d3f275

thread '<unnamed>' panicked at 'assertion failed: n <= self.len()', /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/src/utils.rs:247:9
#16 _$LT$$RF$$u5b$T$u5d$$u20$as$u20$ironrdp..utils..SplitTo$GT$::split_to::hfc5e768e087fe588 /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/src/utils.rs:247:9
#15 0x5616cf635310 in _$LT$ironrdp..preconnection..PreconnectionPdu$u20$as$u20$ironrdp..PduBufferParsing$GT$::from_buffer_consume::h01c56dbd8c3b66e6 /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/src/preconnection.rs:56:37
#16 0x5616cf5a2454 in ironrdp::PduBufferParsing::from_buffer::h558dcc3f32184fe2 /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/src/lib.rs:42:9

In the crash case, the input data ends at the size value that is read in PreconnectionPdu::from_buffer_consume. size * 2 is past the end of buffer, which is then of size 0.

            Version::V2 => {
                let size = buffer.read_u16::<LittleEndian>()? as usize;
                let payload_bytes = buffer.split_to(size * 2);
55	                let size = buffer.read_u16::<LittleEndian>()? as usize;
(gdb) print buffer
$3 = &[u8] {data_ptr: 0x603000000110 "\001\000", length: 2}
(gdb) n
56	                let payload_bytes = buffer.split_to(size * 2);
(gdb) print buffer
$4 = &[u8] {data_ptr: 0x603000000112 "\000", length: 0}

Support for hardware cursor in the browser web client

The cursor image should be set by updating the CSS.

It’s possible to inline the raw bitmap by encoding it in base64:

url(data:image/bmp;base64,Qk06AAAAAAAAADYAAAAoAAAAAQAAAAEAAAABABgAAAAAAAQAAADEDgAAxA4AAAAAAAAAAAAAAgD+AA==)

Note that:

  • It’s okay to not handle animated cursor in an efficient way because it’s a pretty rare scenario. If it works out of the box or if there is an easy solution to increase the performance, it’s nice, but no need to put too much effort into supporting this.
  • Some cursor icons such as the I-beam have "invert color" pixels. I’m not sure it’s possible to set invert pixels using CSS. Maybe there is something smart to do with mix-blend-mode, but it’s fine to consider these pixels as black if it’s too much trouble.

Panic in UserDataHeader::from_buffer due to integer overflow

In UserDataHeader::from_buffer, the program panics if block_length is smaller than USER_DATA_HEADER_SIZE.

https://github.com/Devolutions/IronRDP/blob/master/ironrdp/src/gcc.rs#L383

let block_length = buffer.read_u16::<LittleEndian>()?;

let mut block_data = vec![0; block_length as usize - USER_DATA_HEADER_SIZE];

A fix would be to return an error if block_length is smaller than USER_DATA_HEADER_SIZE.

Backtrace:

  #0 0x5608ba01dde1 in __sanitizer_print_stack_trace /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/llvm-project/compiler-rt/lib/asan/asan_stack.cc:86:3
    #1 0x5608ba309ff5 in fuzzer::PrintStackTrace() /home/sduquette/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/4a41319/libfuzzer/FuzzerUtil.cpp:206:5
    #2 0x5608ba321bb3 in fuzzer::Fuzzer::CrashCallback() /home/sduquette/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/4a41319/libfuzzer/FuzzerLoop.cpp:237:3
    #3 0x5608ba321b51 in fuzzer::Fuzzer::StaticCrashSignalCallback() /home/sduquette/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/4a41319/libfuzzer/FuzzerLoop.cpp:209:6
    #4 0x5608ba314fd7 in fuzzer::CrashHandler(int, siginfo_t*, void*) /home/sduquette/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/4a41319/libfuzzer/FuzzerUtilPosix.cpp:36:3
    #5 0x7f1962483f3f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x13f3f)
    #6 0x7f19622aeed6 in __libc_signal_restore_set /build/glibc-KRRWSm/glibc-2.29/signal/../sysdeps/unix/sysv/linux/internal-signals.h:84:10
    #7 0x7f19622aeed6 in gsignal /build/glibc-KRRWSm/glibc-2.29/signal/../sysdeps/unix/sysv/linux/raise.c:48:3
    #8 0x7f1962290534 in abort /build/glibc-KRRWSm/glibc-2.29/stdlib/abort.c:79:7
    #9 0x5608ba346636 in std::sys::unix::abort_internal::h8e5d5e95c8d55e12 /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/sys/unix/mod.rs:155:4
    #10 0x5608ba3423e5 in std::process::abort::h872a01eae4d63489 /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/process.rs:1575:13
    #11 0x5608ba2e154b in libfuzzer_sys::initialize::_$u7b$$u7b$closure$u7d$$u7d$::hf8a82ccdc7c2a24f /home/sduquette/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/4a41319/src/lib.rs:32:12
    #12 0x5608ba3457a5 in std::panicking::rust_panic_with_hook::h3ccc79b44ba3c353 /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/panicking.rs:481:16
    #13 0x5608ba345241 in std::panicking::continue_panic_fmt::h6da01b9bb2c73c79 /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/panicking.rs:384:4
    #14 0x5608ba345125 in rust_begin_unwind /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/panicking.rs:311:4
    #15 0x5608ba35c0dc in core::panicking::panic_fmt::h52bd9c4c06b66d8d /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libcore/panicking.rs:85:13
    #16 0x5608ba35c01b in core::panicking::panic::h1fb303f1c113605d /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libcore/panicking.rs:49:4
    #17 0x5608b9f61637 in _$LT$ironrdp..gcc..UserDataHeader$LT$T$GT$$u20$as$u20$ironrdp..PduParsing$GT$::from_buffer::h67337ec29fda00c4 /home/sduquette/git/Wayk/IronRDP/ironrdp/src/gcc.rs:383:37
    #18 0x5608b9f5bdcc in _$LT$ironrdp..gcc..ClientGccBlocks$u20$as$u20$ironrdp..PduParsing$GT$::from_buffer::h1529abd3d6024dc7 /home/sduquette/git/Wayk/IronRDP/ironrdp/src/gcc.rs:86:33
    #19 0x5608b9fa18d7 in rust_fuzzer_test_input /home/sduquette/git/Wayk/IronRDP/ironrdp/fuzz/fuzz_targets/fuzz_gcc.rs:8:12
    #20 0x5608ba2e1314 in libfuzzer_sys::test_input_wrap::_$u7b$$u7b$closure$u7d$$u7d$::h935bf9a37ba5666b /home/sduquette/.cargo/git/checkouts/libfuzzer-sys-e07fde05820d7bc6/4a41319/src/lib.rs:11:8
    #21 0x5608ba338b83 in std::panicking::try::do_call::ha98d1e3726717e92 /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libstd/panicking.rs:296:39
    #22 0x5608ba346648 in __rust_maybe_catch_panic /rustc/311376d30dc1cfa622142a9f50317b1e0cb4608a/src/libpanic_abort/lib.rs:29:4

Fuzz(pdu_decoding): panicked for [3, 44, 0, 12, 7, 208, 236, 92, 147, 155, 106, 2, 155, 155, 155, 58]

Relevant workflow run: https://github.com/Devolutions/IronRDP/actions/runs/5239166018/jobs/9458787097

Output:

   thread '<unnamed>' panicked at 'range end index 19 out of range for slice of length 16', /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/cursor.rs:39:22
  stack backtrace:
     0: rust_begin_unwind
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/std/src/panicking.rs:593:5
     1: core::panicking::panic_fmt
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/core/src/panicking.rs:67:14
     2: core::slice::index::slice_end_index_len_fail_rt
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/core/src/slice/index.rs:76:5
     3: core::slice::index::slice_end_index_len_fail
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/core/src/slice/index.rs:68:9
     4: <ironrdp_pdu::nego::ConnectionConfirm as ironrdp_pdu::x224::X224Pdu>::x224_body_decode
     5: ironrdp_pdu::x224::<impl ironrdp_pdu::PduDecode for T>::decode
               at /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/x224.rs:85:9
     6: ironrdp_pdu::decode
               at /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/lib.rs:183:5
     7: ironrdp_fuzzing::oracles::pdu_decode
               at /home/runner/work/IronRDP/IronRDP/crates/ironrdp-fuzzing/src/oracles/mod.rs:22:13
     8: rust_fuzzer_test_input
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/src/lib.rs:224:17
     9: libfuzzer_sys::test_input_wrap::{{closure}}
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/src/lib.rs:61:9
    10: std::panicking::try::do_call
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/std/src/panicking.rs:500:40
    11: __rust_try
    12: std::panicking::try
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/std/src/panicking.rs:464:19
    13: std::panic::catch_unwind
               at /rustc/37998ab508d5d9fa0d465d7b535dc673087dda8f/library/std/src/panic.rs:142:14
    14: LLVMFuzzerTestOneInput
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/src/lib.rs:59:22
    15: _ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/libfuzzer/FuzzerLoop.cpp:612:15
    16: _ZN6fuzzer6Fuzzer6RunOneEPKhmbPNS_9InputInfoEbPb
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/libfuzzer/FuzzerLoop.cpp:514:22
    17: _ZN6fuzzer6Fuzzer16MutateAndTestOneEv
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/libfuzzer/FuzzerLoop.cpp:758:25
    18: _ZN6fuzzer6Fuzzer4LoopERSt6vectorINS_9SizedFileESaIS2_EE
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/libfuzzer/FuzzerLoop.cpp:903:21
    19: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/libfuzzer/FuzzerDriver.cpp:912:10
    20: main
               at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.6/libfuzzer/FuzzerMain.cpp:20:30
    21: __libc_start_main
    22: _start
  note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
  ==3149== ERROR: libFuzzer: deadly signal
      #0 0x56186d97f761  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xca1761) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #1 0x56186ef4b620  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x226d620) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #2 0x56186ef1d03a  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x223f03a) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #3 0x7fe02893b41f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f) (BuildId: 7b4536f41cdaa5888408e82d0836e33dcf436466)
      #4 0x7fe02862100a  (/lib/x86_64-linux-gnu/libc.so.6+0x4300a) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #5 0x7fe028600858  (/lib/x86_64-linux-gnu/libc.so.6+0x22858) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #6 0x56186efe1916  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2303916) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #7 0x56186d8d94d6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbfb4d6) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #8 0x56186ef1a574  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x223c574) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #9 0x56186efd5f4c  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x22f7f4c) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #10 0x56186efd5ce6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x22f7ce6) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #11 0x56186efd31b5  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x22f51b5) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #12 0x56186efd5a31  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x22f7a31) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #13 0x56186d8dcbf2  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbfebf2) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #14 0x56186d8dd281  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbff281) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #15 0x56186e13d68c  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x145f68c) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #16 0x56186da3b0ba  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd5d0ba) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #17 0x56186db2218b  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xe4418b) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #18 0x56186d9b6ab8  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xcd8ab8) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #19 0x56186ef15638  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2237638) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #20 0x56186ef1a787  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x223c787) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #21 0x56186ef19b45  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x223bb45) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #22 0x56186ef1d57c  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x223f57c) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #23 0x56186ef269b3  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x22489b3) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #24 0x56186ef27784  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2249784) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #25 0x56186ef29c87  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x224bc87) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #26 0x56186ef4a909  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x226c909) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #27 0x56186d8dd506  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbff506) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
      #28 0x7fe028602082  (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #29 0x56186d8dd6ad  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbff6ad) (BuildId: 0b8f6eecb0f3397409a054d92241a06a3e993d2c)
  
  NOTE: libFuzzer has rudimentary signal handlers.
        Combine libFuzzer with AddressSanitizer or similar for better crash reports.
  SUMMARY: libFuzzer: deadly signal
  MS: 3 ChangeBinInt-ChangeBinInt-EraseBytes-; base unit: af60a6003dadf91af2da99c34c358da860265042
  0x3,0x2c,0x0,0xc,0x7,0xd0,0xec,0x5c,0x93,0x9b,0x6a,0x2,0x9b,0x9b,0x9b,0x3a,
  \003,\000\014\007\320\354\\\223\233j\002\233\233\233:
  artifact_prefix='/home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/'; Test unit written to /home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/crash-f8dc2df3f2aba63122b8912dff23e13210b408e9
  Base64: AywADAfQ7FyTm2oCm5ubOg==
  
  ────────────────────────────────────────────────────────────────────────────────
  
  Failing input:
  
  	artifacts/pdu_decoding/crash-f8dc2df3f2aba63122b8912dff23e13210b408e9
  
  Output of `std::fmt::Debug`:
  
  	[3, 44, 0, 12, 7, 208, 236, 92, 147, 155, 106, 2, 155, 155, 155, 58]
  
  Reproduce with:
  
  	cargo fuzz run pdu_decoding artifacts/pdu_decoding/crash-f8dc2df3f2aba63122b8912dff23e13210b408e9
  
  Minimize test case with:
  
  	cargo fuzz tmin pdu_decoding artifacts/pdu_decoding/crash-f8dc2df3f2aba63122b8912dff23e13210b408e9
  
  ────────────────────────────────────────────────────────────────────────────────

Fuzz(pdu_decoding): panicked for [3, 44, 0, 12, 2, 240, 92, 105, 127, 255, 138, 138]

Relevant workflow run: https://github.com/Devolutions/IronRDP/actions/runs/4996418558

Output:

  thread '<unnamed>' panicked at 'range end index 13 out of range for slice of length 12', /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/cursor.rs:37:22
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  ==1861== ERROR: libFuzzer: deadly signal
      #0 0x5585fcb2dfe1  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xc55fe1) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #1 0x5585fe034a40  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x215ca40) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #2 0x5585fe02735a  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x214f35a) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #3 0x7f0a6a04141f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f) (BuildId: 7b4536f41cdaa5888408e82d0836e33dcf436466)
      #4 0x7f0a69d2700a  (/lib/x86_64-linux-gnu/libc.so.6+0x4300a) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #5 0x7f0a69d06858  (/lib/x86_64-linux-gnu/libc.so.6+0x22858) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #6 0x5585fe0e94f6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x22114f6) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #7 0x5585fca87da6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbafda6) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #8 0x5585fe024894  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x214c894) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #9 0x5585fe0ddba6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2205ba6) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #10 0x5585fe0dd926  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2205926) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #11 0x5585fe0dae95  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2202e95) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #12 0x5585fe0dd691  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2205691) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #13 0x5585fca8b472  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbb3472) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #14 0x5585fca8bb01  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbb3b01) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #15 0x5585fd2c662a  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x13ee62a) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #16 0x5585fd2add5b  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x13d5d5b) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #17 0x5585fcbe7bd3  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd0fbd3) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #18 0x5585fccc874b  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xdf074b) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #19 0x5585fcb64c95  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xc8cc95) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #20 0x5585fe01ff18  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2147f18) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #21 0x5585fe024aa7  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x214caa7) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #22 0x5585fe023ee5  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x214bee5) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #23 0x5585fe02789c  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x214f89c) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #24 0x5585fe030cd3  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2158cd3) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #25 0x5585fe031aa4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2159aa4) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #26 0x5585fe033fa7  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x215bfa7) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #27 0x5585fe04c9e9  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21749e9) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #28 0x5585fca8bdc6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbb3dc6) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
      #29 0x7f0a69d08082  (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #30 0x5585fca8bf2d  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xbb3f2d) (BuildId: c424fe2cb6d5bd528efad97eec4fac00aab22ee3)
  
  NOTE: libFuzzer has rudimentary signal handlers.
        Combine libFuzzer with AddressSanitizer or similar for better crash reports.
  SUMMARY: libFuzzer: deadly signal
  MS: 1 ChangeBit-; base unit: 0294f3c7c3fef59674ea44011c82ece453d33a4f
  0x3,0x2c,0x0,0xc,0x2,0xf0,0x5c,0x69,0x7f,0xff,0x8a,0x8a,
  \003,\000\014\002\360\\i\177\377\212\212
  artifact_prefix='/home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/'; Test unit written to /home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/crash-ce45f9ebf4ab1a51fcd0175952b22ab0fbcdc392
  Base64: AywADALwXGl//4qK
  
  ────────────────────────────────────────────────────────────────────────────────
  
  Failing input:
  
  	artifacts/pdu_decoding/crash-ce45f9ebf4ab1a51fcd0175952b22ab0fbcdc392
  
  Output of `std::fmt::Debug`:

   	[3, 44, 0, 12, 2, 240, 92, 105, 127, 255, 138, 138]

[Meta] Client-side hardware cursor

Instead of blending the cursor into the frame buffer, it’s much more efficient to set the hardware cursor.

I’m not aware of any crate which handle setting the icon for the hardware cursor directly.
winit only allow setting the "cursor info" (Help, VerticalText, etc).
For the native client, we should create a new crate ironrdp-native-cursor-icon similar to ironrdp-native-clipboard, providing a cross-platform API for setting the cursor.

Issue per platform:

Note: the code for blending the cursor into the frame buffer should not be removed. It can be useful when implementing proxy-based recording and is also a good fallback for platforms where hardware cursor is not supported.

Fuzz(pdu_decoding): panicked for [3, 44, 0, 12, 2, 240, 92, 101, 0, 0, 0, 0]

Relevant Fuzz workflow run: https://github.com/Devolutions/IronRDP/actions/runs/4976146822

Output:

   thread '<unnamed>' panicked at 'range end index 13 out of range for slice of length 12', /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/cursor.rs:37:22
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  ==3141== ERROR: libFuzzer: deadly signal
      #0 0x55894a78e571  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xc48571) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #1 0x55894bc75ca0  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x212fca0) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #2 0x55894bc685ba  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21225ba) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #3 0x7fe912a3141f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f) (BuildId: 7b4536f41cdaa5888408e82d0836e33dcf436466)
      #4 0x7fe91271700a  (/lib/x86_64-linux-gnu/libc.so.6+0x4300a) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #5 0x7fe9126f6858  (/lib/x86_64-linux-gnu/libc.so.6+0x22858) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #6 0x55894bd2a756  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21e4756) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #7 0x55894a6e8336  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xba2336) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #8 0x55894bc65af4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x211faf4) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #9 0x55894bd1ee06  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21d8e06) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #10 0x55894bd1eb86  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21d8b86) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #11 0x55894bd1c0f5  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21d60f5) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #12 0x55894bd1e8f1  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x21d88f1) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #13 0x55894a6eba02  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xba5a02) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #14 0x55894a6ec091  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xba6091) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #15 0x55894af0f8b6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x13c98b6) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #16 0x55894aeff517  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x13b9517) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #17 0x55894a848865  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd02865) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #18 0x55894a929664  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xde3664) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #19 0x55894a7c5225  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xc7f225) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #20 0x55894bc61178  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x211b178) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #21 0x55894bc65d07  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x211fd07) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #22 0x55894bc65145  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x211f145) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #23 0x55894bc68afc  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2122afc) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #24 0x55894bc71f33  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x212bf33) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #25 0x55894bc72d04  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x212cd04) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #26 0x55894bc75207  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x212f207) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #27 0x55894bc8dc49  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x2147c49) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #28 0x55894a6ec356  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xba6356) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
      #29 0x7fe9126f8082  (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #30 0x55894a6ec4bd  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xba64bd) (BuildId: 0dada46b7333aac66692767e8677a42ecb9a21b5)
  
  NOTE: libFuzzer has rudimentary signal handlers.
        Combine libFuzzer with AddressSanitizer or similar for better crash reports.
  SUMMARY: libFuzzer: deadly signal
  MS: 1 EraseBytes-; base unit: 43d844bcbc5b4da91f35ef724272806f93884b06
  0x3,0x2c,0x0,0xc,0x2,0xf0,0x5c,0x65,0x0,0x0,0x0,0x0,
  \003,\000\014\002\360\\e\000\000\000\000
  artifact_prefix='/home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/'; Test unit written to /home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/crash-430f7a29f8e658c25f7e3b5e0763e139facaa4d9
  Base64: AywADALwXGUAAAAA
  
  ────────────────────────────────────────────────────────────────────────────────
  
  Failing input:
  
  	artifacts/pdu_decoding/crash-430f7a29f8e658c25f7e3b5e0763e139facaa4d9
  
  Output of `std::fmt::Debug`:
  
  	[3, 44, 0, 12, 2, 240, 92, 101, 0, 0, 0, 0]
  
  Reproduce with:
  
  	cargo fuzz run pdu_decoding artifacts/pdu_decoding/crash-430f7a29f8e658c25f7e3b5e0763e139facaa4d9

Send all the join requests in a single batch

RDP 4.0, 5.0, 5.1, 5.2, 6.0, 6.1, 7.0, 7.1, 8.0, 10.2, 10.3, 10.4, and 10.5 clients send a Channel Join Request to the server only after the Channel Join Confirm for a previously sent request has been received. RDP 8.1, 10.0, and 10.1 clients send all of the Channel Join Requests to the server in a single batch to minimize the overall connection sequence time.

Let’s send all the Join Requests in a single batch in IronRDP.

TODO comment in code

acceptor: sometime assert on expecting X224 but get FastPath

Sometime, mstsc fails to connect to the server:

2023-10-16T10:33:33.038633Z DEBUG ironrdp_acceptor: Wait for PDU acceptor.state="ConnectionFinalization" hint=X224Hint
2023-10-16T10:33:33.038638Z TRACE ironrdp_acceptor: PDU received length=40
2023-10-16T10:33:33.038644Z DEBUG ironrdp_acceptor::finalization: Received ShareControlHeader { share_control_pdu: Data(ShareDataHeader { share_data_pdu: Control(ControlPdu { action: Cooperate, grant_id: 0, control_id: 0 }), stream_priority: Low, compression_flags: CompressionFlags(0x0), compression_type: K8 }), pdu_source: 1002, share_id: 0 }
[crates/ironrdp-acceptor/src/finalization.rs:62] &self.state = WaitRequestControl
2023-10-16T10:33:33.038652Z DEBUG ironrdp_acceptor: Wait for PDU acceptor.state="ConnectionFinalization" hint=X224Hint
2023-10-16T10:33:33.038657Z TRACE ironrdp_acceptor: PDU received length=40
2023-10-16T10:33:33.038662Z DEBUG ironrdp_acceptor::finalization: Received ShareControlHeader { share_control_pdu: Data(ShareDataHeader { share_data_pdu: Control(ControlPdu { action: RequestControl, grant_id: 0, control_id: 0 }), stream_priority: Low, compression_flags: CompressionFlags(0x0), compression_type: K8 }), pdu_source: 1002, share_id: 0 }
[crates/ironrdp-acceptor/src/finalization.rs:62] &self.state = WaitFontList
2023-10-16T10:33:33.038670Z DEBUG ironrdp_acceptor: Wait for PDU acceptor.state="ConnectionFinalization" hint=X224Hint
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `FastPath`,
 right: `X224`', crates/ironrdp-pdu/src/lib.rs:338:17
stack backtrace:
   0: rust_begin_unwind
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/std/src/panicking.rs:593:5
   1: core::panicking::panic_fmt
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:67:14
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed
             at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library/core/src/panicking.rs:229:5
   4: <ironrdp_pdu::X224Hint as ironrdp_pdu::PduHint>::find_size
             at ./crates/ironrdp-pdu/src/lib.rs:338:17
   5: ironrdp_async::framed::Framed<S>::read_by_hint::{{closure}}
             at ./crates/ironrdp-async/src/framed.rs:164:19
   6: ironrdp_acceptor::single_accept_state::{{closure}}
             at ./crates/ironrdp-acceptor/src/lib.rs:85:14
   7: ironrdp_acceptor::accept_finalize::{{closure}}
             at ./crates/ironrdp-acceptor/src/lib.rs:62:62
   8: ironrdp_server::server::RdpServer::run_connection::{{closure}}
             at ./crates/ironrdp-server/src/server.rs:99:92
   9: ironrdp_server::server::RdpServer::run::{{closure}}
             at ./crates/ironrdp-server/src/server.rs:117:57
  10: server::run::{{closure}}

Indeed, there seems to be some input messages before the FontList:
Screenshot from 2023-10-16 14-37-14

Troubleshooting `iron-svelte-client`

I'm attempting to run iron-svelte-client locally, however am only able to get it to show me a blank black canvas.

Environment

My setup is that I'm running

npm run dev-all

from iron-svelte-client in one terminal, and am running a local build of the devolutions-gateway binary in another.

My gateway.json looks like

{
  "Id": "cf66df0e-f7a9-4ba1-99b1-abe5df5ebefa",
  "ProvisionerPublicKeyFile": "/Users/ibeckermayer/devolutions-config/provisioner.pem",
  "TlsCertificateFile": null,
  "TlsPrivateKeyFile": null,
  "Listeners": [
    {
      "InternalUrl": "tcp://*:8181",
      "ExternalUrl": "tcp://*:8181"
    },
    {
      "InternalUrl": "ws://*:7171",
      "ExternalUrl": "wss://*:7171"
    }
  ],
  "__debug__": {
    "disable_token_validation": true
  }
}

I'm generating a token via a local build of tokengen like

./target/release/tokengen --provisioner-key /Users/ibeckermayer/devolutions-config/provisioner.key forward --dst-hst 127.0.0.1 --jet-ap rdp

and am port forwarding 3389 to the same port on a VM running Windows 11 (I've also tried this with a Windows Server instance running in AWS).

Problem

I can apparently connect to the RDP server, however once I'm connected, all I ever see is a blank screen like below:

image

When I check the browser console, I see a bunch of logs that look like the following

Received Bitmap: Bitmap { rectangles_number: 5, rectangles: [BitmapData:[Rectangle { left: 1088, top: 640, right: 1151, bottom: 703 },
            width - 64,
            height - 64,
            bits_per_pixel - 32,
            compression_flags - (COMPRESSED_HDR | NOT_COMPRESSED),
            compressed_data_header - None
            
Received Bitmap data buffer with length - 1119
], BitmapData:[Rectangle { left: 1152, top: 640, right: 1215, bottom: 703 },
            width - 64,
            height - 64,
            bits_per_pixel - 32,
            compression_flags - (COMPRESSED_HDR | NOT_COMPRESSED),
            compressed_data_header - None
            
Received Bitmap data buffer with length - 1541
], BitmapData:[Rectangle { left: 1216, top: 640, right: 1279, bottom: 703 },
            width - 64,
            height - 64,
            bits_per_pixel - 32,
            compression_flags - (COMPRESSED_HDR | NOT_COMPRESSED),
            compressed_data_header - None
            
Received Bitmap data buffer with length - 2170
], BitmapData:[Rectangle { left: 1152, top: 704, right: 1215, bottom: 719 },
            width - 64,
            height - 16,
            bits_per_pixel - 32,
            compression_flags - (COMPRESSED_HDR | NOT_COMPRESSED),
            compressed_data_header - None
            
Received Bitmap data buffer with length - 135
], BitmapData:[Rectangle { left: 1216, top: 704, right: 1279, bottom: 719 },
            width - 64,
            height - 16,
            bits_per_pixel - 32,
            compression_flags - (COMPRESSED_HDR | NOT_COMPRESSED),
            compressed_data_header - None
            
Received Bitmap data buffer with length - 636
]] }

I've chased those down to this line in the codebase:

Ok(FastPathUpdate::Bitmap(bitmap)) => {
info!("Received Bitmap: {:?}", bitmap);
Ok(None)
}

It looks like I'm convincing the server to send me back fast path bitmaps rather than surface commands, and that this client doesn't fully support bitmaps at this time.

What I've Tried

I'm not sure if this is the case, but I noticed that in the README you mention that RFX should be enabled. I tried to follow your instructions regarding how to enable it, but was only able to find the first of the settings (which I switched on, this is Windows 11 Pro).

image

I haven't found any mention in the RDP documentation that these Surface Commands are related to RemoteFX, any clarification on that would be much appreciated.

Mimic freerdp command-line interface

IronRDP command-line interface should be compatible with FreeRDP. In other word, a valid IronRDP command should be a valid FreeRDP command.

However, Windows-style /arg parameters should not be supported. Only the Linux-style --arg.

Jira Issue: ARC-150

Web Client - client name injection

In native clients, this field contains the first 15 characters of the client machine hostname. We can’t easily retrieve the machine hostname in a web browser, so currently there is a placeholder in the WASM module.

TODO comment in code

Fuzz(pdu_decoding): panicked for [3, 44, 0, 12, 2, 240, 0, 60, 0, 8, 0, 1]

Relevant Fuzz workflow run: https://github.com/Devolutions/IronRDP/actions/runs/4939817833

Output:

  thread '<unnamed>' panicked at 'range end index 13 out of range for slice of length 12', /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/cursor.rs:37:22
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  ==4301== ERROR: libFuzzer: deadly signal
      #0 0x55fbe0c20a21  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xb8ba21) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #1 0x55fbe0de5fc0  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd50fc0) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #2 0x55fbe0d9f3aa  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd0a3aa) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #3 0x7fe9f346541f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f) (BuildId: 7b4536f41cdaa5888408e82d0836e33dcf436466)
      #4 0x7fe9f314b00a  (/lib/x86_64-linux-gnu/libc.so.6+0x4300a) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #5 0x7fe9f312a858  (/lib/x86_64-linux-gnu/libc.so.6+0x22858) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #6 0x55fbe207c5e6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fe75e6) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #7 0x55fbe0b7a7e6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae57e6) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #8 0x55fbe0d9c8e4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd078e4) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #9 0x55fbe2070c96  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fdbc96) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #10 0x55fbe2070a16  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fdba16) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #11 0x55fbe206df85  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fd8f85) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #12 0x55fbe2070781  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fdb781) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #13 0x55fbe0b7deb2  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae8eb2) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #14 0x55fbe0b7e541  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae9541) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #15 0x55fbe12e5b26  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1250b26) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #16 0x55fbe12d9589  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1244589) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #17 0x55fbe0cd2f15  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xc3df15) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #18 0x55fbe0d92144  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xcfd144) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #19 0x55fbe0d90d55  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xcfbd55) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #20 0x55fbe0d97f68  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd02f68) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #21 0x55fbe0d9caf7  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd07af7) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #22 0x55fbe0d9bf35  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd06f35) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #23 0x55fbe0d9f8ec  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd0a8ec) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #24 0x55fbe0da8d23  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd13d23) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #25 0x55fbe0da9af4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd14af4) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #26 0x55fbe0dabff7  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd16ff7) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #27 0x55fbe0dc7a79  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd32a79) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #28 0x55fbe0b7e806  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae9806) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #29 0x7fe9f312c082  (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #30 0x55fbe0b7e96d  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae996d) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
  
  NOTE: libFuzzer has rudimentary signal handlers.
        Combine libFuzzer with AddressSanitizer or similar for better crash reports.
  SUMMARY: libFuzzer: deadly signal
  MS: 1 ChangeBinInt-; base unit: a455e74e00d8ee295cf3d6813766e025fa62f464
  0x3,0x2c,0x0,0xc,0x2,0xf0,0x0,0x3c,0x0,0x8,0x0,0x1,
  \003,\000\014\002\360\000<\000\010\000\001
  artifact_prefix='/home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/'; Test unit written to /home/runner/work/IronRDP/IronRDP/fuzz/artifacts/pdu_decoding/crash-43677392fa06dda5f014e42dd06c9ae05cd19469
  Base64: AywADALwADwACAAB
  
  ────────────────────────────────────────────────────────────────────────────────
  
  Failing input:
  
  	artifacts/pdu_decoding/crash-43677392fa06dda5f014e42dd06c9ae05cd19469
  
  Output of `std::fmt::Debug`:
  
  	[3, 44, 0, 12, 2, 240, 0, 60, 0, 8, 0, 1]
  
  Reproduce with:
  
  	cargo fuzz run pdu_decoding artifacts/pdu_decoding/crash-43677392fa06dda5f014e42dd06c9ae05cd19469
  
  Minimize test case with:
  
  	cargo fuzz tmin pdu_decoding artifacts/pdu_decoding/crash-43677392fa06dda5f014e42dd06c9ae05cd19469

Support for RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN

If the client set the RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN flag in the earlyCapabilityFlags field of the Client Core Data (section 2.2.1.3.2), and the server set the RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED flag in earlyCapabilityFlags field of the Server Core Data (section 2.2.1.4.2), then the MCS Channel Join Request PDUs (section 2.2.1.8) and the MCS Channel Join Confirm PDUs (section 2.2.1.9) SHOULD be skipped to reduce the connection time. Upon reception of the MCS Attach User Confirm PDU (section 2.2.1.7) all the MCS channels (the user channel, the I/O channel, the message channel, and all static virtual channels) SHOULD be considered as fully joined by the client. The client SHOULD NOT send any MCS Channel Join Request PDUs to server and SHOULD proceed to the RDP Security Commencement phase (section 1.3.1.1).

(doc)

Fuzz(pdu_decoding): panicked at 'attempt to subtract with overflow', crates/ironrdp-pdu/src/mcs.rs:656:46

Fuzz workflow found a panic:

  Failing input:
  
  	artifacts/pdu_decoding/crash-65a50aad850d86155cae8c4c28f2937812cce53e
  
  Output of `std::fmt::Debug`:
  
  	[3, 44, 0, 12, 2, 240, 2, 107, 36, 48, 0, 224, 125, 107, 2, 1, 0, 2, 2, 2, 92, 127, 102, 35, 10, 1, 2, 2, 2, 107, 36, 48, 0, 224, 125, 107, 2, 1, 0, 2, 2, 2, 107, 58, 36]
   
  Reproduce with:
  
  	cargo fuzz run pdu_decoding artifacts/pdu_decoding/crash-65a50aad850d86155cae8c4c28f2937812cce53e

Relevant run.

Full stacktrace:

  thread '<unnamed>' panicked at 'attempt to subtract with overflow', /home/runner/work/IronRDP/IronRDP/crates/ironrdp-pdu/src/mcs.rs:656:46
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  ==4483== ERROR: libFuzzer: deadly signal
      #0 0x5579114eea21  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xb8ba21) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #1 0x5579116b3fc0  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd50fc0) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #2 0x55791166d3aa  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd0a3aa) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #3 0x7fa02a95041f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f) (BuildId: 7b4536f41cdaa5888408e82d0836e33dcf436466)
      #4 0x7fa02a63600a  (/lib/x86_64-linux-gnu/libc.so.6+0x4300a) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #5 0x7fa02a615858  (/lib/x86_64-linux-gnu/libc.so.6+0x22858) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #6 0x55791294a5e6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fe75e6) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #7 0x5579114487e6  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae57e6) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #8 0x55791166a8e4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd078e4) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #9 0x55791293ec96  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fdbc96) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #10 0x55791293e9d0  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fdb9d0) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #11 0x55791293bf85  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fd8f85) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #12 0x55791293e781  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x1fdb781) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #13 0x55791144beb2  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae8eb2) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #14 0x55791144bf42  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae8f42) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #15 0x557911bb958b  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x125658b) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #16 0x557911ba79b4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0x12449b4) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #17 0x5579115a0f15  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xc3df15) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #18 0x557911660144  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xcfd144) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #19 0x55791165ed55  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xcfbd55) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #20 0x557911665f68  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd02f68) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #21 0x55791166aaf7  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd07af7) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #22 0x557911669f35  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd06f35) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #23 0x55791166d8ec  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd0a8ec) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #24 0x557911676d23  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd13d23) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #25 0x557911677af4  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd14af4) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #26 0x557911679ff7  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd16ff7) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #27 0x557911695a79  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xd32a79) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #28 0x55791144c806  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae9806) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)
      #29 0x7fa02a617082  (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)
      #30 0x55791144c96d  (/home/runner/work/IronRDP/IronRDP/fuzz/target/x86_64-unknown-linux-gnu/release/pdu_decoding+0xae996d) (BuildId: 57833648bb0f80fe949bf09dd6be422b011643d8)

Fast-path error when connecting to windows 11

Trying to connect to a windows 11 non domain joined machine using the latest build i get this error: RDP failed because of RDP error: Surface Commands error: Received invalid Fast-Path package with 0 length. I will debug this in a few days but checking if this is a known issue already.

Here are the last few lines from the trace command:

Received Bitmap data buffer with length - 1001
], BitmapData:[Rectangle { left: 1856, top: 1024, right: 1919, bottom: 1079 },
width - 64,
height - 56,
bits_per_pixel - 32,
compression_flags - (COMPRESSED_HDR | NOT_COMPRESSED),
compressed_data_header - None

Received Bitmap data buffer with length - 944
]] }
[2022-10-06][21:50:03:795109][DEBUG] Got Fast-Path Header: FastPathHeader { flags: (empty), data_length: 3, forced_long_length: false }
[2022-10-06][21:50:03:795144][DEBUG] Fast-Path Update fragmentation: Single
[2022-10-06][21:50:03:795162][WARN] Received unsupported Fast-Path update: HiddenPointer
[2022-10-06][21:50:04:136938][DEBUG] Got Session Save Info PDU: SaveSessionInfoPdu { info_type: Logon, info_data: LogonInfoV1(LogonInfoVersion1 { logon_info: LogonInfo { session_id: 3, user_name: "sabansal", domain_name: "sabansal-win1" } }) }
[2022-10-06][21:50:04:137177][ERROR] RDP error: Surface Commands error: Received invalid Fast-Path package with 0 length

Support KDC proxy URL injected in web client

In order to support Kerberos in the IronRDP web client, we need a proper build with the sspi-rsnetwork_client feature enabled. KDC detection is not required, since we'll inject a KDC proxy URL (https) into IronRDP, and we need a way to pass it down to sspi-rs through the Rust APIs to be used properly. Once we have this, web-based, RDP connections through the Devolutions Gateway should be able to use Kerberos properly.

Draft PR enabling the missing features: #154

If reqwest is a problem for in-browser blocking HTTP calls, the new ehttp crate can be used instead.

[ERROR] Fast-Path error: Bitmap error: Invalid first row size, must be 0

Reproduction

Setup

Deploy a Windows server 2022 machine in OpenStack and verify that you can establish an RDP connection with a known good RDP client.

Build and run latest IronRDP client from the command line.

Connect to the server using the IronRDP client

Run

Run IronRDP from the command line like this:

cargo run – 192.168.10.10:3389 --username username --password ********

The connection will terminate

[ERROR] Fast-Path error: Bitmap error: Invalid first row size, must be 0, but got: 17197

You should find an error similar to above at the end of ironrdp_client.log

Visual artifacts when using RFX Codec

I noticed there are visual artifacts when the RFX Codec is used with some versions of Windows (Server 2022).
I suspect there may be an off-by-1 error somewhere in the decoder.

Target Windows specifications:

Edition	Windows Server 2022 Standard
Version	21H2
Installed on	‎2023-‎08-‎10
OS build	20348.1906

With RFX Codec (faulty)

faulty.webm

With 16-bit RLE Bitmap Codec (healthy)

healthy.webm

Support Server Redirection PDUs

REDIRECTION_SUPPORTED
0x00000001

The client can receive server session redirection packets. If this flag
is set, the ServerSessionRedirectionVersionMask MUST contain the
server session redirection version that the client supports.

Support static build, Support windows xp. use vs2017

default build is ok!

my rustup defualt:

stable-i686-pc-windows-msvc (default)

but I add my .cargo/config file to workspace dir

[target.x86_64-pc-windows-msvc]
rustflags = ["-Ctarget-feature=+crt-static","-Clink-arg=/SUBSYSTEM:WINDOWS,5.01","-Clink-arg=/ENTRY:mainCRTStartup"]
[target.i686-pc-windows-msvc]
rustflags = ["-Ctarget-feature=+crt-static","-Clink-arg=/SUBSYSTEM:WINDOWS,5.01","-Clink-arg=/ENTRY:mainCRTStartup"]

err:

  = note:    Creating library P:\workspace\local\IronRDP\target\debug\deps\instant-d649f92fcf921fa2.dll.lib and object P:\workspace\local\IronRDP\target\debug\deps\instant-d649f92fcf921fa2.dll.exp
          P:\workspace\local\IronRDP\target\debug\deps\instant-d649f92fcf921fa2.dll : warning LNK4086: entrypoint '_mainCRTStartup' is not __stdcall with 12 bytes of arguments; image may not run
          libcmt.lib(exe_main.obj) : error LNK2019: unresolved external symbol _main referenced in function "int __cdecl __scrt_common_main_seh(void)" (?__scrt_common_main_seh@@YAHXZ)
          P:\workspace\local\IronRDP\target\debug\deps\instant-d649f92fcf921fa2.dll : fatal error LNK1120: 1 unresolved externals

wasm-pack build not possible

Hi,

when i am trying to build a webassembly file with wasm-pack build in the dir "ffi/wasm" I ran into following issue:

error[E0432]: unresolved import crate::sys::IoSourceState--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:12:5 | 12 | use crate::sys::IoSourceState; | ^^^^^^^^^^^^^^^^^^^^^^^^^ noIoSourceStateinsys`

error[E0432]: unresolved import crate::sys::tcp
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:15:17
|
15 | use crate::sys::tcp::{bind, listen, new_for_addr};
| ^^^ could not find tcp in sys

error[E0432]: unresolved import crate::sys::tcp
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/stream.rs:13:17
|
13 | use crate::sys::tcp::{connect, new_for_addr};
| ^^^ could not find tcp in sys

error[E0433]: failed to resolve: could not find Selector in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/poll.rs:301:18
|
301 | sys::Selector::new().map(|selector| Poll {
| ^^^^^^^^ could not find Selector in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:24:14
|
24 | sys::event::token(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:38:14
|
38 | sys::event::is_readable(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:43:14
|
43 | sys::event::is_writable(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:68:14
|
68 | sys::event::is_error(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:99:14
|
99 | sys::event::is_read_closed(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:129:14
|
129 | sys::event::is_write_closed(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:151:14
|
151 | sys::event::is_priority(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:173:14
|
173 | sys::event::is_aio(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:183:14
|
183 | sys::event::is_lio(&self.inner)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find event in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:221:26
|
221 | sys::event::debug_details(f, self.0)
| ^^^^^ could not find event in sys

error[E0433]: failed to resolve: could not find tcp in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:103:18
|
103 | sys::tcp::accept(inner).map(|(stream, addr)| (TcpStream::from_std(stream), addr))
| ^^^ could not find tcp in sys

error[E0433]: failed to resolve: could not find udp in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/udp.rs:122:14
|
122 | sys::udp::bind(addr).map(UdpSocket::from_std)
| ^^^ could not find udp in sys

error[E0433]: failed to resolve: could not find udp in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/udp.rs:544:14
|
544 | sys::udp::only_v6(&self.inner)
| ^^^ could not find udp in sys

error[E0412]: cannot find type Selector in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/poll.rs:255:20
|
255 | selector: sys::Selector,
| ^^^^^^^^ not found in sys

error[E0412]: cannot find type Selector in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/poll.rs:689:44
|
689 | pub(crate) fn selector(&self) -> &sys::Selector {
| ^^^^^^^^ not found in sys

error[E0412]: cannot find type Waker in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/waker.rs:79:17
|
79 | inner: sys::Waker,
| ^^^^^ not found in sys
|
help: consider importing one of these items
|
1 | use core::task::Waker;
|
1 | use crate::Waker;
|
1 | use std::task::Waker;
|
help: if you import Waker, refer to it directly
|
79 - inner: sys::Waker,
79 + inner: Waker,
|

error[E0433]: failed to resolve: could not find Waker in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/waker.rs:87:14
|
87 | sys::Waker::new(registry.selector(), token).map(|inner| Waker { inner })
| ^^^^^ not found in sys
|
help: consider importing one of these items
|
1 | use core::task::Waker;
|
1 | use crate::Waker;
|
1 | use std::task::Waker;
|
help: if you import Waker, refer to it directly
|
87 - sys::Waker::new(registry.selector(), token).map(|inner| Waker { inner })
87 + Waker::new(registry.selector(), token).map(|inner| Waker { inner })
|

error[E0412]: cannot find type Event in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:18:17
|
18 | inner: sys::Event,
| ^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::event::Event;
|
help: if you import Event, refer to it directly
|
18 - inner: sys::Event,
18 + inner: Event,
|

error[E0412]: cannot find type Event in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:187:55
|
187 | pub(crate) fn from_sys_event_ref(sys_event: &sys::Event) -> &Event {
| ^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::event::Event;
|
help: if you import Event, refer to it directly
|
187 - pub(crate) fn from_sys_event_ref(sys_event: &sys::Event) -> &Event {
187 + pub(crate) fn from_sys_event_ref(sys_event: &Event) -> &Event {
|

error[E0412]: cannot find type Event in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:191:41
|
191 | &*(sys_event as *const sys::Event as const Event)
| ^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::event::Event;
|
help: if you import Event, refer to it directly
|
191 - &
(sys_event as *const sys::Event as const Event)
191 + &
(sys_event as *const Event as *const Event)
|

error[E0412]: cannot find type Event in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/event.rs:217:46
|
217 | struct EventDetails<'a>(&'a sys::Event);
| ^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::event::Event;
|
help: if you import Event, refer to it directly
|
217 - struct EventDetails<'a>(&'a sys::Event);
217 + struct EventDetails<'a>(&'a Event);
|

error[E0412]: cannot find type Events in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/events.rs:43:17
|
43 | inner: sys::Events,
| ^^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::Events;
|
help: if you import Events, refer to it directly
|
43 - inner: sys::Events,
43 + inner: Events,
|

error[E0433]: failed to resolve: could not find Events in sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/events.rs:94:25
|
94 | inner: sys::Events::with_capacity(capacity),
| ^^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::Events;
|
help: if you import Events, refer to it directly
|
94 - inner: sys::Events::with_capacity(capacity),
94 + inner: Events::with_capacity(capacity),
|

error[E0412]: cannot find type Events in module sys
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/events.rs:189:47
|
189 | pub(crate) fn sys(&mut self) -> &mut sys::Events {
| ^^^^^^ not found in sys
|
help: consider importing this struct
|
1 | use crate::Events;
|
help: if you import Events, refer to it directly
|
189 - pub(crate) fn sys(&mut self) -> &mut sys::Events {
189 + pub(crate) fn sys(&mut self) -> &mut Events {
|

error[E0425]: cannot find function set_reuseaddr in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:74:9
|
74 | set_reuseaddr(&listener.inner, true)?;
| ^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find value listener in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:74:24
|
74 | set_reuseaddr(&listener.inner, true)?;
| ^^^^^^^^ not found in this scope

error[E0425]: cannot find value listener in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:76:15
|
76 | bind(&listener.inner, addr)?;
| ^^^^^^^^ not found in this scope

error[E0425]: cannot find value listener in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:77:17
|
77 | listen(&listener.inner, 1024)?;
| ^^^^^^^^ not found in this scope

error[E0425]: cannot find value listener in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:78:12
|
78 | Ok(listener)
| ^^^^^^^^ not found in this scope

error[E0425]: cannot find value stream in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/stream.rs:90:18
|
90 | connect(&stream.inner, addr)?;
| ^^^^^^ not found in this scope

error[E0425]: cannot find value stream in this scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/stream.rs:91:12
|
91 | Ok(stream)
| ^^^^^^ not found in this scope

error[E0599]: no method named register found for struct IoSource<std::net::TcpListener> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:146:20
|
146 | self.inner.register(registry, token, interests)
| ^^^^^^^^ method not found in IoSource<std::net::TcpListener>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method register not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item register, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named reregister found for struct IoSource<std::net::TcpListener> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:155:20
|
155 | self.inner.reregister(registry, token, interests)
| ^^^^^^^^^^ method not found in IoSource<std::net::TcpListener>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method reregister not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item reregister, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named deregister found for struct IoSource<std::net::TcpListener> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/listener.rs:159:20
|
159 | self.inner.deregister(registry)
| ^^^^^^^^^^ method not found in IoSource<std::net::TcpListener>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method deregister not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item deregister, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named register found for struct IoSource<std::net::TcpStream> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/stream.rs:325:20
|
325 | self.inner.register(registry, token, interests)
| ^^^^^^^^ method not found in IoSource<std::net::TcpStream>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method register not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item register, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named reregister found for struct IoSource<std::net::TcpStream> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/stream.rs:334:20
|
334 | self.inner.reregister(registry, token, interests)
| ^^^^^^^^^^ method not found in IoSource<std::net::TcpStream>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method reregister not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item reregister, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named deregister found for struct IoSource<std::net::TcpStream> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/tcp/stream.rs:338:20
|
338 | self.inner.deregister(registry)
| ^^^^^^^^^^ method not found in IoSource<std::net::TcpStream>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method deregister not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item deregister, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named register found for struct IoSource<std::net::UdpSocket> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/udp.rs:622:20
|
622 | self.inner.register(registry, token, interests)
| ^^^^^^^^ method not found in IoSource<std::net::UdpSocket>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method register not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item register, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named reregister found for struct IoSource<std::net::UdpSocket> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/udp.rs:631:20
|
631 | self.inner.reregister(registry, token, interests)
| ^^^^^^^^^^ method not found in IoSource<std::net::UdpSocket>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method reregister not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item reregister, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

error[E0599]: no method named deregister found for struct IoSource<std::net::UdpSocket> in the current scope
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/net/udp.rs:635:20
|
635 | self.inner.deregister(registry)
| ^^^^^^^^^^ method not found in IoSource<std::net::UdpSocket>
|
::: /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/io_source.rs:62:1
|
62 | pub struct IoSource {
| ---------------------- method deregister not found for this struct
|
= help: items from traits can only be used if the trait is implemented and in scope
note: Source defines an item deregister, perhaps you need to implement it
--> /home/niklas/.cargo/registry/src/github.com-1ecc6299db9ec823/mio-0.8.5/src/event/source.rs:75:1
|
75 | pub trait Source {
| ^^^^^^^^^^^^^^^^

Some errors have detailed explanations: E0412, E0425, E0432, E0433, E0599.
For more information about an error, try rustc --explain E0412.
error: could not compile mio due to 44 previous errors
warning: build failed, waiting for other jobs to finish...
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute cargo build: exited with exit status: 101
full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"`

  • rustc --version rustc 1.65.0 (897e37553 2022-11-02)
  • cargo 1.65.0 (4bc8f24d3 2022-10-20)
  • current main branch
  • error occures under win10 and debian

Best regards,

Niklas

Fix UTF-16 string length computations

Some code in IronRDP is incorrectly computing the size of UTF-16 strings.

Example:

// This is not the right way to compute the number of bytes for unicode strings encoded in UTF-16.
// This is a time bomb: it will returns the correct result some times (e.g.: when the string is valid ASCII),
// but not always.
fn utf16_len(utf8_str: &str) -> usize {
    utf8_str.len() * 2
}

Both UTF-8 and UTF-16 are using a variable-length encoding and code points may be encoded using multiple code units. The thing is, UTF-16 uses one or two 16-bit code units and UTF-8 uses between one and four 8-bit code units. It’s really not always the case that a code point in UTF-16 is twice as big as the same code point in UTF-8.

This kind of erroneous code is present at multiple places. One such instance is ironrdp_pdu::rdp::client_info::string_len.

Instead, something like that must be used:

utf8_str.encode_utf16().count() * 2 // add 2 if we need to account for a null terminator (0x0000)

Refer to ironrdp_pdu::pcb module for a correct implementation.

Preserve unknown bitmask bits values in PDUs (eliminate use of 'from_bits_truncate')

To prevent losing information after PDU encode/decode roundtrip, we should always keep bitmask values unchanged, but currently, we use from_bits_truncate excessively in the codebase. As @CBenoit explained in the comment, we need to avoid usage of from_bits_truncate:

we should either use from_bits or from_bits_retain, but never from_bits_truncate, and I would tend to reach for from_bits_retain over from_bits

Rationale:

  • We want the round-tripping property to hold, and for this property to hold, parsing must be non destructive (lossless), but from_bits_truncate is destructive (undefined bits are discarded)
  • We generally want lenient parsing, ignoring unknown values as long as we don’t need them and/or as long as ignoring them is causing no harm, but from_bits is not lenient

However, it’s okay to use from_bits if strictness is required at some place, but I would like such places to be documented with a comment explaining why we have to refuse unknown flags

Unbounded allocation in ProductInfo::from_buffer

fuzz_pdu panics due to a very large allocation in ProductInfo::from_buffer. company_name_len and product_id_len are read from the server and used directly as an allocation size.

        let company_name_len = stream.read_u32::<LittleEndian>()?;
        if company_name_len < 2 {
            return Err(ServerLicenseError::InvalidProductInfoStringField);
        }

        let mut company_name = vec![0u8; company_name_len as usize];

Stacktrace

==17238== ERROR: libFuzzer: out-of-memory (malloc(3239510016))

 #14 0x561b4aef201c in alloc::vec::from_elem::h68c60dd992591487 /rustc/85976442558bf2d09cec3aa49c9c9ba86fb15c1f/src/liballoc/vec.rs:1722:4
    #15 0x561b4adb252c in _$LT$ironrdp..rdp..server_license..server_license_request..ProductInfo$u20$as$u20$ironrdp..PduParsing$GT$::from_buffer::heb80a67c194ab28f /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/fuzz/<::alloc::macros::vec macros>:1:33
    #16 0x561b4adb82b2 in _$LT$ironrdp..rdp..server_license..server_license_request..ServerLicenseRequest$u20$as$u20$ironrdp..PduParsing$GT$::from_buffer::hab00f9ddb1418f5d /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/src/rdp/server_license/server_license_request.rs:159:27
    #17 0x561b4acf02ea in rust_fuzzer_test_input /home/sduquette/Devolutions/Wayk/IronRDP/ironrdp/fuzz/fuzz_targets/fuzz_pdu.rs:25:12

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.