Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rdpdr): DR_CORE_SERVER_CLIENTID_CONFIRM and DR_CORE_DEVICELIST_ANNOUNCE #193

Merged
merged 7 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ expect-test = "1"
proptest = "1.1.0"
rstest = "0.17.0"
sspi = "0.10.1"
tracing = "0.1.37"
tracing = { version = "0.1.37", features = ["log"] }
thiserror = "1.0.40"

[profile.dev]
Expand Down
2 changes: 2 additions & 0 deletions crates/ironrdp-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ native-tls = ["ironrdp-tls/native-tls"]
ironrdp = { workspace = true, features = ["input", "graphics", "dvc", "rdpdr", "rdpsnd", "cliprdr"] }
ironrdp-tls.workspace = true
ironrdp-tokio.workspace = true
ironrdp-rdpsnd.workspace = true
ironrdp-rdpdr.workspace = true
sspi = { workspace = true, features = ["network_client", "dns_resolver"] } # enable additional features

# GUI
Expand Down
2 changes: 1 addition & 1 deletion crates/ironrdp-client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use tap::prelude::*;
const DEFAULT_WIDTH: u16 = 1920;
const DEFAULT_HEIGHT: u16 = 1080;

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Config {
pub log_file: String,
pub destination: Destination,
Expand Down
4 changes: 3 additions & 1 deletion crates/ironrdp-client/src/rdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async fn connect(config: &Config) -> ConnectorResult<(ConnectionResult, Upgraded
.with_credssp_network_client(RequestClientFactory)
// .with_static_channel(ironrdp::dvc::Drdynvc::new()) // FIXME: drdynvc is not working
.with_static_channel(ironrdp::rdpsnd::Rdpsnd::new())
.with_static_channel(ironrdp::rdpdr::Rdpdr::default())
.with_static_channel(ironrdp_rdpdr::Rdpdr::new("IronRDP".to_string()).with_smartcard(0))
.with_static_channel(ironrdp::cliprdr::Cliprdr::default());

let should_upgrade = ironrdp_tokio::connect_begin(&mut framed, &mut connector).await?;
Expand All @@ -122,6 +122,8 @@ async fn connect(config: &Config) -> ConnectorResult<(ConnectionResult, Upgraded

let connection_result = ironrdp_tokio::connect_finalize(upgraded, &mut upgraded_framed, connector).await?;

debug!(?connection_result);

Ok((connection_result, upgraded_framed))
}

Expand Down
8 changes: 4 additions & 4 deletions crates/ironrdp-cliprdr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ impl Cliprdr {
self.state = CliprdrState::Failed;
error!("CLIPRDR(clipboard) failed: {err}");

Ok(vec![])
Ok(Vec::new())
}

fn handle_server_capabilities(&mut self, server_capabilities: Capabilities) -> PduResult<Vec<SvcMessage>> {
self.capabilities.downgrade(&server_capabilities);

// Do not send anything, wait for monitor ready pdu
Ok(vec![])
Ok(Vec::new())
}

fn handle_monitor_ready(&mut self) -> PduResult<Vec<SvcMessage>> {
Expand All @@ -99,7 +99,7 @@ impl Cliprdr {
}
}

Ok(vec![])
Ok(Vec::new())
}
}

Expand All @@ -126,7 +126,7 @@ impl StaticVirtualChannel for Cliprdr {

if self.state == CliprdrState::Failed {
error!("Attempted to process clipboard static virtual channel in failed state");
return Ok(vec![]);
return Ok(Vec::new());
}

match pdu {
Expand Down
3 changes: 2 additions & 1 deletion crates/ironrdp-fuzzing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ test = false
arbitrary = { version = "1", features = ["derive"] }
ironrdp-graphics.workspace = true
ironrdp-pdu.workspace = true
ironrdp-cliprdr.workspace = true
ironrdp-cliprdr.workspace = true
ironrdp-rdpdr.workspace = true
2 changes: 2 additions & 0 deletions crates/ironrdp-fuzzing/src/oracles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ pub fn pdu_decode(data: &[u8]) {
let _ = decode::<bitmap::rdp6::BitmapStream>(data);

let _ = decode::<ironrdp_cliprdr::pdu::ClipboardPdu>(data);

let _ = decode::<ironrdp_rdpdr::pdu::RdpdrPdu>(data);
}

pub fn rle_decompress_bitmap(input: BitmapInput) {
Expand Down
2 changes: 1 addition & 1 deletion crates/ironrdp-graphics/src/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl DecodedPointer {
});
}

let mut bitmap_data = vec![];
let mut bitmap_data = Vec::new();

for row_idx in 0..data.height {
// For non-monochrome cursors we read strides from bottom to top
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-graphics/src/rectangle_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1477,7 +1477,7 @@ mod tests {
right: 0,
bottom: 0,
},
rectangles: vec![],
rectangles: Vec::new(),
};
let input_rectangle = InclusiveRectangle {
left: 5,
Expand All @@ -1499,7 +1499,7 @@ mod tests {
right: 0,
bottom: 0,
},
rectangles: vec![],
rectangles: Vec::new(),
};
let input_rectangle = InclusiveRectangle {
left: 5,
Expand Down
46 changes: 31 additions & 15 deletions crates/ironrdp-rdpdr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
//!
//! [\[MS-RDPEFS\]: Remote Desktop Protocol: File System Virtual Channel Extension]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/34d9de58-b2b5-40b6-b970-f82d4603bdb5

mod pdu;
pub mod pdu;
use crate::pdu::{
efs::{
CapabilityMessage, ClientNameRequest, ClientNameRequestUnicodeFlag, CoreCapability, CoreCapabilityKind,
VersionAndIdPdu, VersionAndIdPduKind,
ClientNameRequest, ClientNameRequestUnicodeFlag, CoreCapability, CoreCapabilityKind, VersionAndIdPdu,
VersionAndIdPduKind,
},
RdpdrPdu,
};
use ironrdp_pdu::{decode, gcc::ChannelName, other_err, PduResult};
use ironrdp_svc::{impl_as_any, CompressionCondition, StaticVirtualChannel, SvcMessage};
use pdu::efs::{Capabilities, ClientDeviceListAnnounce, Devices};
use tracing::{trace, warn};

/// The RDPDR channel as specified in [\[MS-RDPEFS\]].
Expand All @@ -27,25 +28,31 @@ use tracing::{trace, warn};
pub struct Rdpdr {
/// TODO: explain what this is
computer_name: String,
capabilities: Vec<CapabilityMessage>,
}

impl Default for Rdpdr {
fn default() -> Self {
Self::new("IronRDP".to_string(), vec![CapabilityMessage::new_general(0)])
}
capabilities: Capabilities,
/// Pre-configured list of devices to announce to the server.
///
/// All devices not of the type [`DeviceType::Filesystem`] must be declared here.
device_list: Devices,
}

impl Rdpdr {
pub const NAME: ChannelName = ChannelName::from_static(b"rdpdr\0\0\0");

pub fn new(computer_name: String, capabilities: Vec<CapabilityMessage>) -> Self {
/// Creates a new [`Rdpdr`].
pub fn new(computer_name: String) -> Self {
Self {
computer_name,
capabilities,
capabilities: Capabilities::new(),
device_list: Devices::new(),
}
}

pub fn with_smartcard(mut self, device_id: u32) -> Self {
self.device_list.add_smartcard(device_id);
self.capabilities.add_smartcard();
self
}

fn handle_server_announce(&mut self, req: VersionAndIdPdu) -> PduResult<Vec<SvcMessage>> {
let client_announce_reply = RdpdrPdu::VersionAndIdPdu(VersionAndIdPdu::new_client_announce_reply(req)?);
trace!("sending {:?}", client_announce_reply);
Expand All @@ -63,10 +70,16 @@ impl Rdpdr {
}

fn handle_server_capability(&mut self, _req: CoreCapability) -> PduResult<Vec<SvcMessage>> {
let res = RdpdrPdu::CoreCapability(CoreCapability::new_response(self.capabilities.clone()));
let res = RdpdrPdu::CoreCapability(CoreCapability::new_response(self.capabilities.clone_inner()));
trace!("sending {:?}", res);
Ok(vec![SvcMessage::from(res)])
}

// TODO: Make CoreCapability PduEncode
fn handle_client_id_confirm(&mut self) -> PduResult<Vec<SvcMessage>> {
let res = RdpdrPdu::ClientDeviceListAnnounce(ClientDeviceListAnnounce {
device_list: self.device_list.clone_inner(),
});
trace!("sending {:?}", res);
Ok(vec![SvcMessage::from(res)])
}
}
Expand All @@ -93,9 +106,12 @@ impl StaticVirtualChannel for Rdpdr {
RdpdrPdu::CoreCapability(pdu) if pdu.kind == CoreCapabilityKind::ServerCoreCapabilityRequest => {
self.handle_server_capability(pdu)
}
RdpdrPdu::VersionAndIdPdu(pdu) if pdu.kind == VersionAndIdPduKind::ServerClientIdConfirm => {
self.handle_client_id_confirm()
}
RdpdrPdu::Unimplemented => {
warn!("received unimplemented packet: {:?}", pdu);
Ok(vec![])
Ok(Vec::new())
}
_ => Err(other_err!("rdpdr", "internal error")),
}
Expand Down
Loading