citronneur / rdp-rs Goto Github PK
View Code? Open in Web Editor NEWRemote Desktop Protocol in RUST
License: MIT License
Remote Desktop Protocol in RUST
License: MIT License
Is there any plan to support the Session Selection Extension https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeps/83aeefd1-c4a1-4807-8072-2a597c8cf19b so you can connect to a hyper-v virtual machine through the host instead of needing the IP address of the guest?
According to the protocol and the implementation in freerdp it looks quite straightforward.
Unfortunately my attempt ran into a wall of a not answering server after I issued the message described in the above document.
Does anyone know why I can't use the install command. I'm running it under macOS (ARM).
cargo install rdp-rs --features=mstsc-rs
Updating crates.io index
Installing rdp-rs v0.1.0
Compiling libc v0.2.137
Compiling autocfg v1.1.0
Compiling cfg-if v1.0.0
Compiling typenum v1.15.0
Compiling bitflags v1.3.2
Compiling proc-macro2 v1.0.47
Compiling semver v1.0.14
Compiling quote v1.0.21
Compiling version_check v0.9.4
Compiling memchr v2.5.0
Compiling lexical-core v0.7.6
Compiling unicode-ident v1.0.5
Compiling serde v1.0.148
Compiling num-traits v0.2.15
Compiling core-foundation-sys v0.8.3
Compiling nom v5.1.2
Compiling num-integer v0.1.45
Compiling static_assertions v1.1.0
Compiling arrayvec v0.5.2
Compiling getrandom v0.1.16
Compiling syn v1.0.104
Compiling ryu v1.0.11
Compiling rustc_version v0.4.0
Compiling generic-array v0.12.4
Compiling num-bigint v0.2.6
Compiling byte-tools v0.3.1
Compiling cast v0.2.7
Compiling block-padding v0.1.5
Compiling digest v0.8.1
Compiling time v0.1.45
Compiling byteorder v1.4.3
Compiling gcc v0.3.55
Compiling cc v1.0.77
Compiling cty v0.2.2
Compiling block-buffer v0.7.3
Compiling raw-window-handle v0.4.3
Compiling rand_core v0.5.1
Compiling rand v0.4.6
Compiling security-framework-sys v2.6.1
Compiling rust-crypto v0.2.36
Compiling core-foundation v0.9.3
Compiling indexmap v1.9.2
Compiling minifb v0.15.3
Compiling remove_dir_all v0.5.3
Compiling toml v0.5.9
Compiling ppv-lite86 v0.2.17
Compiling winapi v0.3.9
Compiling subtle v1.0.0
Compiling fastrand v1.8.0
Compiling opaque-debug v0.2.3
Compiling unicode-width v0.1.10
Compiling native-tls v0.2.11
Compiling rand_chacha v0.2.2
Compiling rusticata-macros v2.1.0
Compiling der-parser v3.0.4
Compiling textwrap v0.11.0
Compiling tempfile v3.3.0
Compiling proc-macro-crate v0.1.5
Compiling crypto-mac v0.7.0
Compiling rand v0.3.23
Compiling security-framework v2.7.0
Compiling raw-window-handle v0.3.4
Compiling atty v0.2.14
Compiling strsim v0.8.0
Compiling base64 v0.11.0
Compiling fake-simd v0.1.2
Compiling rustc-serialize v0.3.24
Compiling vec_map v0.8.2
Compiling lazy_static v1.4.0
Compiling ansi_term v0.12.1
Compiling hashbrown v0.12.3
Compiling clap v2.34.0
Compiling x509-parser v0.6.5
Compiling md4 v0.8.0
Compiling hmac v0.7.1
Compiling rand v0.7.3
Compiling md-5 v0.8.0
Compiling derivative v2.2.0
Compiling num_enum_derive v0.4.3
Compiling hex v0.4.3
Compiling bufstream v0.1.4
Compiling yasna v0.3.2
Compiling num_enum v0.4.3
Compiling rdp-rs v0.1.0
error[E0425]: cannot find functionwait_for_fd
in this scope
--> /Users/chxmvn/.cargo/registry/src/github.com-1ecc6299db9ec823/rdp-rs-0.1.0/src/bin/mstsc-rs.rs:325:15
|
325 | while wait_for_fd(handle as usize) && sync.load(Ordering::Relaxed) {
| ^^^^^^^^^^^ not found in this scopeerror[E0425]: cannot find value
handle
in this scope
--> /Users/chxmvn/.cargo/registry/src/github.com-1ecc6299db9ec823/rdp-rs-0.1.0/src/bin/mstsc-rs.rs:543:9
|
543 | handle as usize,
| ^^^^^^ not found in this scopeFor more information about this error, try
rustc --explain E0425
.
error: could not compilerdp-rs
due to 2 previous errors
error: failed to compilerdp-rs v0.1.0
, intermediate artifacts can be found at/var/folders/tv/x2qdcddj3zg_40kh6g2j8_6w0000gn/T/cargo-install5F6cjJ
Lines 124 to 158 in b4804d1
Hi, I've found a couple of panics in the TPKT parsing code that happen when the TPKT header specifies a length of zero. I've observed this happening due to network errors over in nccgroup/scrying#26 and have come up with some local reproductions.
Here are the test cases I used:
#[cfg(test)]
mod repro {
use rdp::core::tpkt::Client;
use rdp::model::link::{Link, Stream};
use std::io::Cursor;
fn process(data: &[u8]) {
let cur = Cursor::new(data.to_vec());
let link = Link::new(Stream::Raw(cur));
let mut client = Client::new(link);
let _ = client.read();
}
#[test]
fn case_1() {
let buf = b"\x00\x00\x03\x00\x00\x00";
process(buf);
}
#[test]
fn case_2() {
let buf = b"\x00\x80\x00\x00\x00\x00";
process(buf);
}
#[test]
fn case_3() {
let buf = b"\x03\xe8\x00\x00\x80\x00";
process(buf);
}
}
0000 0300 0000
---- repro::case_1 stdout ----
thread 'repro::case_1' panicked at 'attempt to subtract with overflow', /home/david/gits/rdp-rs-sciguy16/src/core/tpkt.rs:155:80
stack backtrace:
0: rust_begin_unwind
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panicking.rs:495:5
1: core::panicking::panic_fmt
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:92:14
2: core::panicking::panic
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:50:5
3: rdp::core::tpkt::Client<S>::read
at /home/david/gits/rdp-rs-sciguy16/src/core/tpkt.rs:155:80
4: rdp_afl::repro::process
at ./src/main.rs:32:17
5: rdp_afl::repro::case_1
at ./src/main.rs:38:9
6: rdp_afl::repro::case_1::{{closure}}
at ./src/main.rs:36:5
7: core::ops::function::FnOnce::call_once
at /home/david/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
8: core::ops::function::FnOnce::call_once
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/ops/function.rs:227:5
short_length as usize - 2
subtraction with overflow. In release mode this attempts to allocate a 2^64-2 byte buffer to read into, which fails0080 0000 0000
---- repro::case_3 stdout ----
thread 'repro::case_3' panicked at 'attempt to subtract with overflow', /home/david/gits/rdp-rs-sciguy16/src/core/tpkt.rs:152:80
stack backtrace:
0: rust_begin_unwind
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panicking.rs:495:5
1: core::panicking::panic_fmt
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:92:14
2: core::panicking::panic
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:50:5
3: rdp::core::tpkt::Client<S>::read
at /home/david/gits/rdp-rs-sciguy16/src/core/tpkt.rs:152:80
4: rdp_afl::repro::process
at ./src/main.rs:32:17
5: rdp_afl::repro::case_3
at ./src/main.rs:50:9
6: rdp_afl::repro::case_3::{{closure}}
at ./src/main.rs:48:5
7: core::ops::function::FnOnce::call_once
at /home/david/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
8: core::ops::function::FnOnce::call_once
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/ops/function.rs:227:5
length as usize - 3
subtraction with overflow. In release mode this attempts to allocate a 2^64-3 byte buffer to read into, which fails03e8 0000 8000
---- repro::case_4 stdout ----
thread 'repro::case_4' panicked at 'attempt to subtract with overflow', /home/david/gits/rdp-rs-sciguy16/src/core/tpkt.rs:140:61
stack backtrace:
0: rust_begin_unwind
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/std/src/panicking.rs:495:5
1: core::panicking::panic_fmt
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:92:14
2: core::panicking::panic
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/panicking.rs:50:5
3: rdp::core::tpkt::Client<S>::read
at /home/david/gits/rdp-rs-sciguy16/src/core/tpkt.rs:140:61
4: rdp_afl::repro::process
at ./src/main.rs:32:17
5: rdp_afl::repro::case_4
at ./src/main.rs:56:9
6: rdp_afl::repro::case_4::{{closure}}
at ./src/main.rs:54:5
7: core::ops::function::FnOnce::call_once
at /home/david/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
8: core::ops::function::FnOnce::call_once
at /rustc/e1884a8e3c3e813aada8254edfa120e85bf5ffca/library/core/src/ops/function.rs:227:5
size.inner() as usize - 4
subtraction with overflow. In release mode this attempts to allocate a 2^64-4 byte buffer to read into, which failsAccording to the MS documentation the minimum length of a TPKT packet should be 7, and adding a check for this should resolve the issue here.
Excerpt from [2], section 8:
Since an X.224 TPDU occupies at least 3 octets, the minimum value of TPKT length is 7. The maximum value is 65535. This permits a maximum TPDU size of 65531 octets.
Refs:
[1] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/18a27ef9-6f9a-4501-b000-94b1fe3c2c10
[2] https://www.itu.int/rec/T-REC-T.123-200701-I/en
I found when i connect to my windows server,some error pop up ,it's like
[2022-07-22T09:42:04Z ERROR rdp_client] Rdp(Io(Os { code: 54, kind: ConnectionReset, message: "Connection reset by peer" }))
[2022-07-22T09:42:04Z ERROR rdp_client] invalid Rust client pointer
WARN[0017] failed to close the RDP client rdp-addr="192.168.1.202:3389"
this is my code and
program crashes atx224::Client::connect(tpkt::Client::new(tcp),protocols,false,Some(&mut authentication),false,false)?;
let mut authentication = Ntlm::new(
addr.to_string().clone(),
params.username.clone(),
params.password.clone(),
);
println!("addr:{}",addr.to_string());
println!("username:{}",params.username);
println!("password:{}",params.password);
// From rdp-rs/src/core/client.rs
let tcp = Link::new(Stream::Raw(tcp));
let protocols = x224::Protocols::ProtocolHybrid as u32|x224::Protocols::ProtocolSSL as u32;
let x224 = x224::Client::connect(
tpkt::Client::new(tcp),protocols,false,Some(&mut authentication),false,false)?;
How can I use rdprs to connect to linuxUI in cloud?
First, thanks for writing this code. This is just an observation, no requests.
I work on MeshCentral and I am working on porting your NLA support from the Rust version to the NodeJS version. In working on that, I noticed this code in cssp.rs:
// now server respond normally with the original public key incremented by one
let r2 = &(link.read(0)?);
println!("READ: read_ts_validate {}", hex::encode(&r1));
let inc_pub_key = security_interface.gss_unwrapex(&(read_ts_validate(r2)?))?;
// Check possible man in the middle using cssp
if BigUint::from_bytes_le(&inc_pub_key) != BigUint::from_bytes_le(certificate.tbs_certificate.subject_pki.subject_public_key.data) + BigUint::new(vec![1]) {
return Err(Error::RdpError(RdpError::new(RdpErrorKind::PossibleMITM, "Man in the middle detected")))
}
Looking the the bits received, it seems like ASN1 encoded, not a BigUInt. I would send this challenge:
{
tagClass: 0,
type: 16,
constructed: true,
composed: true,
value: [
{
tagClass: 0,
type: 2,
constructed: false,
composed: false,
value: '..........'
},
{
tagClass: 0,
type: 2,
constructed: false,
composed: false,
value: '.....'
}
]
}
and get this as a response:
{
tagClass: 0,
type: 17,
constructed: true,
composed: true,
value: [
{
tagClass: 0,
type: 2,
constructed: false,
composed: false,
value: '..........'
},
{
tagClass: 0,
type: 2,
constructed: false,
composed: false,
value: '.....'
}
]
}
Only the first "type" changes from 16 to 17, everything else is the same. The BigUInt compare works, but instead, you could check that both prime and exponent are identical.
Hi @citronneur ,
Thanks for your amazing work to bringing us this crate.
I'm trying to build a wasm application based on your work.
But got some unexpected error "Invalid minimal size for TPKT"
I tried to ignore it and it seems can restore itself.
But when looking through your mstsc-rs code, it seems the program shall be terminated when the error occurs
Lines 325 to 344 in 7ac880d
See the screenshot which shows it continues to work when the error shows up.
Do you have any idea about this error? 'cuz I cannot observe it when using the mstsc-rs which makes me confused.
BTW, the errors happens at line 142 #1
, 159 #2
, 166 #3
with the tuple (action, length) shown in the screenshot
Lines 124 to 172 in 7ac880d
Thanks in advance
Hi, do you plan to support plain RDP mode? When I tried to connect to a couple of Server 2003 and XP boxes I get the following error:
RdpError(RdpError { kind: ProtocolNegFailure, message: "Error during negotiation step" })
When I connect with rdesktop it says:
Protocol(warning): Protocol negotiation failed with reason: SSL not allowed by server
Retrying with plain RDP.
Hello,
I am new to Rust but have a great interest in RDP for a project that I am working on now that needs to also have channels to allow for file transfer, audio, video stream, etc.
In the C/C++ world, I know of FreeRDP (https://www.freerdp.com/) which has many useful features, but I would like to use RDP from Rust as my project is being developed in it.
In the recent past, I also ran across RustDesk (https://rustdesk.com/) but I do not think that they are using the MS RDP protocol.
I am wondering if your rdp-rs library supports channels like the standard Windows RDP client or, if not, then how challenging would it be to add some of these?
Thanks and have a great day
There's a RustSec advisory for the rust-crypto dependency which has been unmaintained since 2016. It's probably worth considering switching to crates from the RustCrypto project in the longer term.
What about to add optional serde support for event structs? I use your client in my project and have to write identical wrapper structs with (de)serialize, it's redundantly.
Hello! I get these errors when I try to connect to my Windows 10 machine:
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapstypeShare" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapstypeColorcache" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapsettypeLargePointer" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapstypeFont" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapsettypeBitmapCodecs" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapstypeBitmapcacheHostsupport" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapstypeRail" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapstypeWindow" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapsettypeSurfaceCommands" })
GLOBAL: RdpError(RdpError { kind: Unknown, message: "CAPABILITY: Unknown capability CapssettypeFrameAcknowledge" })
using this code drawn from the examples in the README:
use std::net::{SocketAddr, TcpStream};
use rdp::core::client::Connector;
use rdp::core::event::{RdpEvent, PointerEvent, PointerButton};
fn main() {
let addr = "<MY_IP>:3389".parse::<SocketAddr>().unwrap();
let tcp = TcpStream::connect(&addr).unwrap();
let mut connector = Connector::new()
.screen(800, 600)
.credentials("".to_string(), "Alistair".to_string(), "<MY_PASSWORD>".to_string());
let mut client = connector.connect(tcp).unwrap();
client.write(RdpEvent::Pointer(
// Send a mouse click down at 100x100
PointerEvent {
x: 100 as u16,
y: 100 as u16,
button: PointerButton::Left,
down: true
}
)).unwrap();
client.read(|rdp_event| {
match rdp_event {
RdpEvent::Bitmap(bitmap) => {
dbg!(bitmap.width);
}
_ => println!("Unhandled event")
}
}).unwrap();
}
Any ideas? Cheers!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.