feat(rdpdr): handling for DeviceCloseRequest and DeviceCloseResponse (#257)

This commit is contained in:
Isaiah Becker-Mayer
2023-11-02 00:54:03 -04:00
committed by GitHub
parent cebfe8c6f3
commit c2f57f5bcb
3 changed files with 103 additions and 15 deletions
+8 -4
View File
@@ -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")),
}
}
}
+72 -8
View File
@@ -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
}
}
+23 -3
View File
@@ -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