Skip to content

Commit

Permalink
feat(rdpdr): DR_CORE_SERVER_CLIENTID_CONFIRM and `DR_CORE_DEVICELIS…
Browse files Browse the repository at this point in the history
…T_ANNOUNCE` (#193)

Adds handling for `DR_CORE_SERVER_CLIENTID_CONFIRM` and `DR_CORE_DEVICELIST_ANNOUNCE`/`DR_CORE_DEVICELIST_ANNOUNCE_REQ`.
The next steps in the rdpdr initialization sequence.
  • Loading branch information
Isaiah Becker-Mayer authored Sep 20, 2023
1 parent 86b86ba commit fe1567c
Show file tree
Hide file tree
Showing 19 changed files with 311 additions and 44 deletions.
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 @@ -50,7 +50,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

# Windowing and rendering
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

0 comments on commit fe1567c

Please sign in to comment.