mirror of
https://github.com/netbirdio/IronRDP.git
synced 2026-05-22 18:43:12 -07:00
feat(rdpdr): handling for DeviceCloseRequest and DeviceCloseResponse (#257)
This commit is contained in:
@@ -38,7 +38,10 @@ pub use self::backend::RdpdrBackend;
|
||||
/// [\[MS-RDPEFS\] Appendix A<1>]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/fd28bfd9-dae2-4a78-abe1-b4efa208b7aa#Appendix_A_1
|
||||
#[derive(Debug)]
|
||||
pub struct Rdpdr {
|
||||
/// TODO: explain what this is
|
||||
/// The name of the computer that is running the client.
|
||||
///
|
||||
/// Any directories shared will be displayed by File Explorer
|
||||
/// as "<directory> on <computer_name>".
|
||||
computer_name: String,
|
||||
capabilities: Capabilities,
|
||||
/// Pre-configured list of devices to announce to the server.
|
||||
@@ -54,6 +57,8 @@ impl Rdpdr {
|
||||
pub const NAME: ChannelName = ChannelName::from_static(b"rdpdr\0\0\0");
|
||||
|
||||
/// Creates a new [`Rdpdr`].
|
||||
///
|
||||
/// See [`Rdpdr::computer_name`].
|
||||
pub fn new(backend: Box<dyn RdpdrBackend>, computer_name: String) -> Self {
|
||||
Self {
|
||||
computer_name,
|
||||
@@ -212,9 +217,8 @@ impl StaticVirtualChannelProcessor for Rdpdr {
|
||||
| RdpdrPdu::CoreCapability(_)
|
||||
| RdpdrPdu::DeviceControlResponse(_)
|
||||
| RdpdrPdu::DeviceCreateResponse(_)
|
||||
| RdpdrPdu::ClientDriveQueryInformationResponse(_) => {
|
||||
Err(other_err!("Rdpdr", "received unexpected packet"))
|
||||
}
|
||||
| RdpdrPdu::ClientDriveQueryInformationResponse(_)
|
||||
| RdpdrPdu::DeviceCloseResponse(_) => Err(other_err!("Rdpdr", "received unexpected packet")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1346,23 +1346,20 @@ impl DeviceIoResponse {
|
||||
pub enum ServerDriveIoRequest {
|
||||
ServerCreateDriveRequest(DeviceCreateRequest),
|
||||
ServerDriveQueryInformationRequest(ServerDriveQueryInformationRequest),
|
||||
DeviceCloseRequest(DeviceCloseRequest),
|
||||
}
|
||||
|
||||
impl ServerDriveIoRequest {
|
||||
pub fn decode(dev_io_req: DeviceIoRequest, src: &mut ReadCursor<'_>) -> PduResult<Self> {
|
||||
match dev_io_req.major_function {
|
||||
MajorFunction::Create => Ok(Self::ServerCreateDriveRequest(DeviceCreateRequest::decode(
|
||||
dev_io_req, src,
|
||||
)?)),
|
||||
MajorFunction::Close => todo!(),
|
||||
MajorFunction::Create => Ok(DeviceCreateRequest::decode(dev_io_req, src)?.into()),
|
||||
MajorFunction::Close => Ok(DeviceCloseRequest::decode(dev_io_req).into()),
|
||||
MajorFunction::Read => todo!(),
|
||||
MajorFunction::Write => todo!(),
|
||||
MajorFunction::DeviceControl => todo!(),
|
||||
MajorFunction::QueryVolumeInformation => todo!(),
|
||||
MajorFunction::SetVolumeInformation => todo!(),
|
||||
MajorFunction::QueryInformation => Ok(Self::ServerDriveQueryInformationRequest(
|
||||
ServerDriveQueryInformationRequest::decode(dev_io_req, src)?,
|
||||
)),
|
||||
MajorFunction::QueryInformation => Ok(ServerDriveQueryInformationRequest::decode(dev_io_req, src)?.into()),
|
||||
MajorFunction::SetInformation => todo!(),
|
||||
MajorFunction::DirectoryControl => todo!(),
|
||||
MajorFunction::LockControl => todo!(),
|
||||
@@ -1370,6 +1367,24 @@ impl ServerDriveIoRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeviceCreateRequest> for ServerDriveIoRequest {
|
||||
fn from(req: DeviceCreateRequest) -> Self {
|
||||
Self::ServerCreateDriveRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ServerDriveQueryInformationRequest> for ServerDriveIoRequest {
|
||||
fn from(req: ServerDriveQueryInformationRequest) -> Self {
|
||||
Self::ServerDriveQueryInformationRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeviceCloseRequest> for ServerDriveIoRequest {
|
||||
fn from(req: DeviceCloseRequest) -> Self {
|
||||
Self::DeviceCloseRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
/// [2.2.3.3.1] Server Create Drive Request (DR_DRIVE_CREATE_REQ)
|
||||
/// and [2.2.1.4.1] Device Create Request (DR_CREATE_REQ)
|
||||
///
|
||||
@@ -1408,7 +1423,9 @@ impl DeviceCreateRequest {
|
||||
let path_length: usize = cast_length!("DeviceCreateRequest", "path_length", src.read_u32())?;
|
||||
|
||||
ensure_size!(ctx: "DeviceCreateRequest", in: src, size: path_length);
|
||||
let path = from_utf16_bytes(src.read_slice(path_length));
|
||||
let path = from_utf16_bytes(src.read_slice(path_length))
|
||||
.trim_end_matches('\0')
|
||||
.into();
|
||||
|
||||
Ok(Self {
|
||||
device_io_request: dev_io_req,
|
||||
@@ -1867,3 +1884,50 @@ impl FileAttributeTagInformation {
|
||||
+ 4 // ReparseTag
|
||||
}
|
||||
}
|
||||
|
||||
/// [2.2.1.4.2] Device Close Request (DR_CLOSE_REQ)
|
||||
///
|
||||
/// [2.2.1.4.2]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/3ec6627f-9e0f-4941-a828-3fc6ed63d9e7
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceCloseRequest {
|
||||
pub device_io_request: DeviceIoRequest,
|
||||
// Padding (32 bytes): ignored as per FreeRDP:
|
||||
// https://github.com/FreeRDP/FreeRDP/blob/511444a65e7aa2f537c5e531fa68157a50c1bd4d/channels/drive/client/drive_main.c#L236
|
||||
}
|
||||
|
||||
impl DeviceCloseRequest {
|
||||
pub fn decode(dev_io_req: DeviceIoRequest) -> Self {
|
||||
Self {
|
||||
device_io_request: dev_io_req,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [2.2.1.5.2] Device Close Response (DR_CLOSE_RSP)
|
||||
///
|
||||
/// [2.2.1.5.2]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/0dae7031-cfd8-4f14-908c-ec06e14997b5
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceCloseResponse {
|
||||
pub device_io_response: DeviceIoResponse,
|
||||
// Padding (4 bytes): An array of 4 bytes. Reserved. This field can be set to any value and MUST be ignored.
|
||||
}
|
||||
|
||||
impl DeviceCloseResponse {
|
||||
const NAME: &str = "DR_CLOSE_RSP";
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
pub fn encode(&self, dst: &mut WriteCursor<'_>) -> PduResult<()> {
|
||||
ensure_size!(in: dst, size: self.size());
|
||||
self.device_io_response.encode(dst)?;
|
||||
dst.write_u32(0); // Padding
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.device_io_response.size() // DeviceIoResponse
|
||||
+ 4 // Padding
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ use ironrdp_pdu::{ensure_size, invalid_message_err, PduDecode, PduEncode, PduErr
|
||||
|
||||
use self::efs::{
|
||||
ClientDeviceListAnnounce, ClientDriveQueryInformationResponse, ClientNameRequest, CoreCapability,
|
||||
CoreCapabilityKind, DeviceControlResponse, DeviceCreateResponse, DeviceIoRequest, ServerDeviceAnnounceResponse,
|
||||
VersionAndIdPdu, VersionAndIdPduKind,
|
||||
CoreCapabilityKind, DeviceCloseResponse, DeviceControlResponse, DeviceCreateResponse, DeviceIoRequest,
|
||||
ServerDeviceAnnounceResponse, VersionAndIdPdu, VersionAndIdPduKind,
|
||||
};
|
||||
|
||||
pub mod efs;
|
||||
@@ -24,6 +24,7 @@ pub enum RdpdrPdu {
|
||||
DeviceControlResponse(DeviceControlResponse),
|
||||
DeviceCreateResponse(DeviceCreateResponse),
|
||||
ClientDriveQueryInformationResponse(ClientDriveQueryInformationResponse),
|
||||
DeviceCloseResponse(DeviceCloseResponse),
|
||||
/// TODO: temporary value for development, this should be removed
|
||||
Unimplemented,
|
||||
}
|
||||
@@ -74,7 +75,8 @@ impl RdpdrPdu {
|
||||
},
|
||||
RdpdrPdu::DeviceControlResponse(_)
|
||||
| RdpdrPdu::DeviceCreateResponse(_)
|
||||
| RdpdrPdu::ClientDriveQueryInformationResponse(_) => SharedHeader {
|
||||
| RdpdrPdu::ClientDriveQueryInformationResponse(_)
|
||||
| RdpdrPdu::DeviceCloseResponse(_) => SharedHeader {
|
||||
component: Component::RdpdrCtypCore,
|
||||
packet_id: PacketId::CoreDeviceIoCompletion,
|
||||
},
|
||||
@@ -116,6 +118,7 @@ impl PduEncode for RdpdrPdu {
|
||||
RdpdrPdu::DeviceControlResponse(pdu) => pdu.encode(dst),
|
||||
RdpdrPdu::DeviceCreateResponse(pdu) => pdu.encode(dst),
|
||||
RdpdrPdu::ClientDriveQueryInformationResponse(pdu) => pdu.encode(dst),
|
||||
RdpdrPdu::DeviceCloseResponse(pdu) => pdu.encode(dst),
|
||||
RdpdrPdu::Unimplemented => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -131,6 +134,7 @@ impl PduEncode for RdpdrPdu {
|
||||
RdpdrPdu::DeviceControlResponse(pdu) => pdu.name(),
|
||||
RdpdrPdu::DeviceCreateResponse(pdu) => pdu.name(),
|
||||
RdpdrPdu::ClientDriveQueryInformationResponse(pdu) => pdu.name(),
|
||||
RdpdrPdu::DeviceCloseResponse(pdu) => pdu.name(),
|
||||
RdpdrPdu::Unimplemented => "Unimplemented",
|
||||
}
|
||||
}
|
||||
@@ -147,6 +151,7 @@ impl PduEncode for RdpdrPdu {
|
||||
RdpdrPdu::DeviceControlResponse(pdu) => pdu.size(),
|
||||
RdpdrPdu::DeviceCreateResponse(pdu) => pdu.size(),
|
||||
RdpdrPdu::ClientDriveQueryInformationResponse(pdu) => pdu.size(),
|
||||
RdpdrPdu::DeviceCloseResponse(pdu) => pdu.size(),
|
||||
RdpdrPdu::Unimplemented => 0,
|
||||
}
|
||||
}
|
||||
@@ -182,6 +187,9 @@ impl fmt::Debug for RdpdrPdu {
|
||||
Self::ClientDriveQueryInformationResponse(it) => {
|
||||
write!(f, "RdpdrPdu({:?})", it)
|
||||
}
|
||||
Self::DeviceCloseResponse(it) => {
|
||||
write!(f, "RdpdrPdu({:?})", it)
|
||||
}
|
||||
Self::Unimplemented => {
|
||||
write!(f, "RdpdrPdu::Unimplemented")
|
||||
}
|
||||
@@ -201,6 +209,18 @@ impl From<DeviceCreateResponse> for RdpdrPdu {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ClientDriveQueryInformationResponse> for RdpdrPdu {
|
||||
fn from(value: ClientDriveQueryInformationResponse) -> Self {
|
||||
Self::ClientDriveQueryInformationResponse(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeviceCloseResponse> for RdpdrPdu {
|
||||
fn from(value: DeviceCloseResponse) -> Self {
|
||||
Self::DeviceCloseResponse(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// [2.2.1.1] Shared Header (RDPDR_HEADER), a header that is shared by all RDPDR PDUs.
|
||||
///
|
||||
/// [2.2.1.1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/29d4108f-8163-4a67-8271-e48c4b9c2a7c
|
||||
|
||||
Reference in New Issue
Block a user