feat(rdpdr): DeviceCreateRequest and DeviceCreateResponse (#235)

This commit is contained in:
Isaiah Becker-Mayer
2023-10-30 18:15:25 +00:00
committed by GitHub
parent 8b359ff4a3
commit 9859cb7518
6 changed files with 373 additions and 60 deletions
+2 -1
View File
@@ -1,7 +1,7 @@
pub mod noop;
use crate::pdu::{
efs::{DeviceControlRequest, ServerDeviceAnnounceResponse},
efs::{DeviceControlRequest, FilesystemRequest, ServerDeviceAnnounceResponse},
esc::{ScardCall, ScardIoCtlCode},
};
use core::fmt;
@@ -12,4 +12,5 @@ use ironrdp_svc::AsAny;
pub trait RdpdrBackend: AsAny + fmt::Debug + Send {
fn handle_server_device_announce_response(&mut self, pdu: ServerDeviceAnnounceResponse) -> PduResult<()>;
fn handle_scard_call(&mut self, req: DeviceControlRequest<ScardIoCtlCode>, call: ScardCall) -> PduResult<()>;
fn handle_fs_request(&mut self, req: FilesystemRequest) -> PduResult<()>;
}
+3
View File
@@ -18,4 +18,7 @@ impl RdpdrBackend for NoopRdpdrBackend {
fn handle_scard_call(&mut self, _req: DeviceControlRequest<ScardIoCtlCode>, _call: ScardCall) -> PduResult<()> {
Ok(())
}
fn handle_fs_request(&mut self, _req: crate::pdu::efs::FilesystemRequest) -> PduResult<()> {
Ok(())
}
}
+16 -22
View File
@@ -10,7 +10,7 @@ extern crate tracing;
pub mod backend;
pub mod pdu;
use crate::pdu::efs::MajorFunction;
use crate::pdu::efs::FilesystemRequest;
pub use backend::{noop::NoopRdpdrBackend, RdpdrBackend};
use ironrdp_pdu::{cursor::ReadCursor, decode_cursor, gcc::ChannelName, other_err, PduResult};
use ironrdp_svc::{impl_as_any, CompressionCondition, StaticVirtualChannelProcessor, SvcMessage};
@@ -135,13 +135,13 @@ impl Rdpdr {
fn handle_device_io_request(
&mut self,
pdu: DeviceIoRequest,
payload: &mut ReadCursor<'_>,
dev_io_req: DeviceIoRequest,
src: &mut ReadCursor<'_>,
) -> PduResult<Vec<SvcMessage>> {
match self.device_list.for_device_type(pdu.device_id)? {
match self.device_list.for_device_type(dev_io_req.device_id)? {
DeviceType::Smartcard => {
let req = DeviceControlRequest::<ScardIoCtlCode>::decode(pdu, payload)?;
let call = ScardCall::decode(req.io_control_code, payload)?;
let req = DeviceControlRequest::<ScardIoCtlCode>::decode(dev_io_req, src)?;
let call = ScardCall::decode(req.io_control_code, src)?;
debug!(?req);
debug!(?req.io_control_code, ?call);
@@ -151,24 +151,17 @@ impl Rdpdr {
Ok(Vec::new())
}
DeviceType::Filesystem => {
debug!("received filesystem packet");
match pdu.major_function {
MajorFunction::Create => todo!(),
MajorFunction::Close => todo!(),
MajorFunction::Read => todo!(),
MajorFunction::Write => todo!(),
MajorFunction::DeviceControl => todo!(),
MajorFunction::QueryVolumeInformation => todo!(),
MajorFunction::SetVolumeInformation => todo!(),
MajorFunction::QueryInformation => todo!(),
MajorFunction::SetInformation => todo!(),
MajorFunction::DirectoryControl => todo!(),
MajorFunction::LockControl => todo!(),
}
let req = FilesystemRequest::decode(dev_io_req, src)?;
debug!(?req);
self.backend.handle_fs_request(req)?;
Ok(Vec::new())
}
_ => {
// This should never happen, as we only announce devices that we support.
warn!(?pdu, "received packet for unsupported device type");
warn!(?dev_io_req, "received packet for unsupported device type");
Ok(Vec::new())
}
}
@@ -211,7 +204,8 @@ impl StaticVirtualChannelProcessor for Rdpdr {
| RdpdrPdu::ClientDeviceListAnnounce(_)
| RdpdrPdu::VersionAndIdPdu(_)
| RdpdrPdu::CoreCapability(_)
| RdpdrPdu::DeviceControlResponse(_) => Err(other_err!("Rdpdr", "received unexpected packet")),
| RdpdrPdu::DeviceControlResponse(_)
| RdpdrPdu::DeviceCreateResponse(_) => Err(other_err!("Rdpdr", "received unexpected packet")),
}
}
}
+331 -34
View File
@@ -5,8 +5,9 @@
use super::esc::rpce;
use super::{PacketId, SharedHeader};
use bitflags::bitflags;
use core::fmt;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::utils::{encoded_str_len, write_string_to_cursor, CharacterSet};
use ironrdp_pdu::utils::{encoded_str_len, from_utf16_bytes, write_string_to_cursor, CharacterSet};
use ironrdp_pdu::{cast_length, ensure_size, invalid_message_err, read_padding, write_padding, PduError, PduResult};
use std::fmt::Debug;
use std::mem::size_of;
@@ -952,7 +953,7 @@ impl ServerDeviceAnnounceResponse {
pub fn decode(src: &mut ReadCursor<'_>) -> PduResult<Self> {
ensure_size!(ctx: Self::NAME, in: src, size: Self::FIXED_PART_SIZE);
let device_id = src.read_u32();
let result_code = NtStatus::try_from(src.read_u32())?;
let result_code = NtStatus::from(src.read_u32());
Ok(Self { device_id, result_code })
}
@@ -968,51 +969,66 @@ impl ServerDeviceAnnounceResponse {
/// This enum includes some basic ones for communicating with the RDP server.
///
/// [2.3.1 NTSTATUS Values]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u32)]
pub enum NtStatus {
Success = 0x0000_0000,
Unsuccessful = 0xC000_0001,
NotImplemented = 0xC000_0002,
NoMoreFiles = 0x8000_0006,
ObjectNameCollision = 0xC000_0035,
AccessDenied = 0xC000_0022,
NotADirectory = 0xC000_0103,
NoSuchFile = 0xC000_000F,
NotSupported = 0xC000_00BB,
DirectoryNotEmpty = 0xC000_0101,
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct NtStatus(u32);
impl NtStatus {
/// STATUS_SUCCESS
pub const SUCCESS: Self = Self(0x0000_0000);
/// STATUS_UNSUCCESSFUL
pub const UNSUCCESSFUL: Self = Self(0xC000_0001);
/// STATUS_NOT_IMPLEMENTED
pub const NOT_IMPLEMENTED: Self = Self(0xC000_0002);
/// STATUS_NO_MORE_FILES
pub const NO_MORE_FILES: Self = Self(0x8000_0006);
/// STATUS_OBJECT_NAME_COLLISION
pub const OBJECT_NAME_COLLISION: Self = Self(0xC000_0035);
/// STATUS_ACCESS_DENIED
pub const ACCESS_DENIED: Self = Self(0xC000_0022);
/// STATUS_NOT_A_DIRECTORY
pub const NOT_A_DIRECTORY: Self = Self(0xC000_0103);
/// STATUS_NO_SUCH_FILE
pub const NO_SUCH_FILE: Self = Self(0xC000_000F);
/// STATUS_NOT_SUPPORTED
pub const NOT_SUPPORTED: Self = Self(0xC000_00BB);
/// STATUS_DIRECTORY_NOT_EMPTY
pub const DIRECTORY_NOT_EMPTY: Self = Self(0xC000_0101);
}
impl TryFrom<u32> for NtStatus {
type Error = PduError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0x0000_0000 => Ok(NtStatus::Success),
0xC000_0001 => Ok(NtStatus::Unsuccessful),
0xC000_0002 => Ok(NtStatus::NotImplemented),
0x8000_0006 => Ok(NtStatus::NoMoreFiles),
0xC000_0035 => Ok(NtStatus::ObjectNameCollision),
0xC000_0022 => Ok(NtStatus::AccessDenied),
0xC000_0103 => Ok(NtStatus::NotADirectory),
0xC000_000F => Ok(NtStatus::NoSuchFile),
0xC000_00BB => Ok(NtStatus::NotSupported),
0xC000_0101 => Ok(NtStatus::DirectoryNotEmpty),
_ => Err(invalid_message_err!("try_from", "NtStatus", "unsupported value")),
impl Debug for NtStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
NtStatus::SUCCESS => write!(f, "STATUS_SUCCESS"),
NtStatus::UNSUCCESSFUL => write!(f, "STATUS_UNSUCCESSFUL"),
NtStatus::NOT_IMPLEMENTED => write!(f, "STATUS_NOT_IMPLEMENTED"),
NtStatus::NO_MORE_FILES => write!(f, "STATUS_NO_MORE_FILES"),
NtStatus::OBJECT_NAME_COLLISION => write!(f, "STATUS_OBJECT_NAME_COLLISION"),
NtStatus::ACCESS_DENIED => write!(f, "STATUS_ACCESS_DENIED"),
NtStatus::NOT_A_DIRECTORY => write!(f, "STATUS_NOT_A_DIRECTORY"),
NtStatus::NO_SUCH_FILE => write!(f, "STATUS_NO_SUCH_FILE"),
NtStatus::NOT_SUPPORTED => write!(f, "STATUS_NOT_SUPPORTED"),
NtStatus::DIRECTORY_NOT_EMPTY => write!(f, "STATUS_DIRECTORY_NOT_EMPTY"),
_ => write!(f, "{:#010X}", self.0),
}
}
}
impl From<u32> for NtStatus {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<NtStatus> for u32 {
fn from(status: NtStatus) -> Self {
status as u32
status.0
}
}
/// [2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST)]
///
/// [2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST)]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct DeviceIoRequest {
pub device_id: u32,
pub file_id: u32,
@@ -1265,11 +1281,19 @@ impl DeviceIoResponse {
const NAME: &str = "DR_DEVICE_IOCOMPLETION";
const FIXED_PART_SIZE: usize = size_of::<u32>() * 3; // DeviceId, CompletionId, IoStatus
pub fn new(device_io_request: DeviceIoRequest, io_status: NtStatus) -> Self {
Self {
device_id: device_io_request.device_id,
completion_id: device_io_request.completion_id,
io_status,
}
}
pub fn decode(src: &mut ReadCursor<'_>) -> PduResult<Self> {
ensure_size!(ctx: "DeviceIoResponse", in: src, size: Self::FIXED_PART_SIZE);
let device_id = src.read_u32();
let completion_id = src.read_u32();
let io_status = NtStatus::try_from(src.read_u32())?;
let io_status = NtStatus::from(src.read_u32());
Ok(Self {
device_id,
@@ -1290,3 +1314,276 @@ impl DeviceIoResponse {
Self::FIXED_PART_SIZE
}
}
#[derive(Debug)]
pub enum FilesystemRequest {
DeviceCreateRequest(DeviceCreateRequest),
}
impl FilesystemRequest {
pub fn decode(dev_io_req: DeviceIoRequest, src: &mut ReadCursor<'_>) -> PduResult<Self> {
match dev_io_req.major_function {
MajorFunction::Create => Ok(Self::DeviceCreateRequest(DeviceCreateRequest::decode(dev_io_req, src)?)),
MajorFunction::Close => todo!(),
MajorFunction::Read => todo!(),
MajorFunction::Write => todo!(),
MajorFunction::DeviceControl => todo!(),
MajorFunction::QueryVolumeInformation => todo!(),
MajorFunction::SetVolumeInformation => todo!(),
MajorFunction::QueryInformation => todo!(),
MajorFunction::SetInformation => todo!(),
MajorFunction::DirectoryControl => todo!(),
MajorFunction::LockControl => todo!(),
}
}
}
/// [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)]
///
/// [2.2.3.3.1 Server Create Drive Request (DR_DRIVE_CREATE_REQ)]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/95b16fd0-d530-407c-a310-adedc85e9897
/// [2.2.1.4.1 Device Create Request (DR_CREATE_REQ)]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/5f71f6d2-d9ff-40c2-bdb5-a739447d3c3e
#[derive(Debug)]
pub struct DeviceCreateRequest {
/// The MajorFunction field in this header MUST be set to IRP_MJ_CREATE.
pub device_io_request: DeviceIoRequest,
pub desired_access: DesiredAccess,
pub allocation_size: u64,
pub file_attributes: FileAttributes,
pub shared_access: SharedAccess,
pub create_disposition: CreateDisposition,
pub create_options: CreateOptions,
pub path: String,
}
impl DeviceCreateRequest {
const FIXED_PART_SIZE: usize = 4 // DesiredAccess
+ 8 // AllocationSize
+ 4 // FileAttributes
+ 4 // SharedAccess
+ 4 // CreateDisposition
+ 4 // CreateOptions
+ 4; // PathLength
fn decode(dev_io_req: DeviceIoRequest, src: &mut ReadCursor<'_>) -> PduResult<Self> {
ensure_size!(ctx: "DeviceCreateRequest", in: src, size: Self::FIXED_PART_SIZE);
let desired_access = DesiredAccess::from_bits_retain(src.read_u32());
let allocation_size = src.read_u64();
let file_attributes = FileAttributes::from_bits_retain(src.read_u32());
let shared_access = SharedAccess::from_bits_retain(src.read_u32());
let create_disposition = CreateDisposition::from_bits_retain(src.read_u32());
let create_options = CreateOptions::from_bits_retain(src.read_u32());
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));
Ok(Self {
device_io_request: dev_io_req,
desired_access,
allocation_size,
file_attributes,
shared_access,
create_disposition,
create_options,
path,
})
}
}
bitflags! {
/// DesiredAccess can be interpreted as either
/// [2.2.13.1.1 File_Pipe_Printer_Access_Mask \[MS-SMB2\]] or [2.2.13.1.2 Directory_Access_Mask \[MS-SMB2\]]
///
/// This implements the combination of the two. For flags where the names and/or functions are distinct between the two,
/// the names are appended with an "_OR_", and the File_Pipe_Printer_Access_Mask functionality is described on the top line comment,
/// and the Directory_Access_Mask functionality is described on the bottom (2nd) line comment.
///
/// [2.2.13.1.1 File_Pipe_Printer_Access_Mask \[MS-SMB2\]]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/77b36d0f-6016-458a-a7a0-0f4a72ae1534
/// [2.2.13.1.2 Directory_Access_Mask \[MS-SMB2\]]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/0a5934b1-80f1-4da0-b1bf-5e021c309b71
#[derive(Debug, Clone)]
pub struct DesiredAccess: u32 {
/// This value indicates the right to read data from the file or named pipe.
///
/// This value indicates the right to enumerate the contents of the directory.
const FILE_READ_DATA_OR_FILE_LIST_DIRECTORY = 0x00000001;
/// This value indicates the right to write data into the file or named pipe beyond the end of the file.
///
/// This value indicates the right to create a file under the directory.
const FILE_WRITE_DATA_OR_FILE_ADD_FILE = 0x00000002;
/// This value indicates the right to append data into the file or named pipe.
///
/// This value indicates the right to add a sub-directory under the directory.
const FILE_APPEND_DATA_OR_FILE_ADD_SUBDIRECTORY = 0x00000004;
/// This value indicates the right to read the extended attributes of the file or named pipe.
const FILE_READ_EA = 0x00000008;
/// This value indicates the right to write or change the extended attributes to the file or named pipe.
const FILE_WRITE_EA = 0x00000010;
/// This value indicates the right to traverse this directory if the server enforces traversal checking.
const FILE_TRAVERSE = 0x00000020;
/// This value indicates the right to delete entries within a directory.
const FILE_DELETE_CHILD = 0x00000040;
/// This value indicates the right to execute the file/directory.
const FILE_EXECUTE = 0x00000020;
/// This value indicates the right to read the attributes of the file/directory.
const FILE_READ_ATTRIBUTES = 0x00000080;
/// This value indicates the right to change the attributes of the file/directory.
const FILE_WRITE_ATTRIBUTES = 0x00000100;
/// This value indicates the right to delete the file/directory.
const DELETE = 0x00010000;
/// This value indicates the right to read the security descriptor for the file/directory or named pipe.
const READ_CONTROL = 0x00020000;
/// This value indicates the right to change the discretionary access control list (DACL) in the security descriptor for the file/directory or named pipe. For the DACL data pub structure, see ACL in [MS-DTYP].
const WRITE_DAC = 0x00040000;
/// This value indicates the right to change the owner in the security descriptor for the file/directory or named pipe.
const WRITE_OWNER = 0x00080000;
/// SMB2 clients set this flag to any value. SMB2 servers SHOULD ignore this flag.
const SYNCHRONIZE = 0x00100000;
/// This value indicates the right to read or change the system access control list (SACL) in the security descriptor for the file/directory or named pipe. For the SACL data pub structure, see ACL in [MS-DTYP].
const ACCESS_SYSTEM_SECURITY = 0x01000000;
/// This value indicates that the client is requesting an open to the file with the highest level of access the client has on this file. If no access is granted for the client on this file, the server MUST fail the open with STATUS_ACCESS_DENIED.
const MAXIMUM_ALLOWED = 0x02000000;
/// This value indicates a request for all the access flags that are previously listed except MAXIMUM_ALLOWED and ACCESS_SYSTEM_SECURITY.
const GENERIC_ALL = 0x10000000;
/// This value indicates a request for the following combination of access flags listed above: FILE_READ_ATTRIBUTES| FILE_EXECUTE| SYNCHRONIZE| READ_CONTROL.
const GENERIC_EXECUTE = 0x20000000;
/// This value indicates a request for the following combination of access flags listed above: FILE_WRITE_DATA| FILE_APPEND_DATA| FILE_WRITE_ATTRIBUTES| FILE_WRITE_EA| SYNCHRONIZE| READ_CONTROL.
const GENERIC_WRITE = 0x40000000;
/// This value indicates a request for the following combination of access flags listed above: FILE_READ_DATA| FILE_READ_ATTRIBUTES| FILE_READ_EA| SYNCHRONIZE| READ_CONTROL.
const GENERIC_READ = 0x80000000;
}
}
bitflags! {
/// [2.6 File Attributes \[MS-FSCC\]]
///
/// [2.6 File Attributes \[MS-FSCC\]]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ca28ec38-f155-4768-81d6-4bfeb8586fc9
#[derive(Debug, Clone)]
pub struct FileAttributes: u32 {
const FILE_ATTRIBUTE_READONLY = 0x00000001;
const FILE_ATTRIBUTE_HIDDEN = 0x00000002;
const FILE_ATTRIBUTE_SYSTEM = 0x00000004;
const FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
const FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
const FILE_ATTRIBUTE_NORMAL = 0x00000080;
const FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
const FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
const FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
const FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
const FILE_ATTRIBUTE_OFFLINE = 0x00001000;
const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
const FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
const FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000;
const FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000;
const FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x00040000;
const FILE_ATTRIBUTE_PINNED = 0x00080000;
const FILE_ATTRIBUTE_UNPINNED = 0x00100000;
const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x00400000;
}
}
bitflags! {
/// Specified in [2.2.13 SMB2 CREATE Request]
///
/// [2.2.13 SMB2 CREATE Request]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e8fb45c1-a03d-44ca-b7ae-47385cfd7997
#[derive(Debug, Clone)]
pub struct SharedAccess: u32 {
const FILE_SHARE_READ = 0x00000001;
const FILE_SHARE_WRITE = 0x00000002;
const FILE_SHARE_DELETE = 0x00000004;
}
}
bitflags! {
/// Defined in [2.2.13 SMB2 CREATE Request]
///
/// See FreeRDP's [drive_file.c] for context about how these should be interpreted.
///
/// [2.2.13 SMB2 CREATE Request]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e8fb45c1-a03d-44ca-b7ae-47385cfd7997
/// [drive_file.c]: https://github.com/FreeRDP/FreeRDP/blob/511444a65e7aa2f537c5e531fa68157a50c1bd4d/channels/drive/client/drive_file.c#L207
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct CreateDisposition: u32 {
const FILE_SUPERSEDE = 0x00000000;
const FILE_OPEN = 0x00000001;
const FILE_CREATE = 0x00000002;
const FILE_OPEN_IF = 0x00000003;
const FILE_OVERWRITE = 0x00000004;
const FILE_OVERWRITE_IF = 0x00000005;
}
}
bitflags! {
/// Defined in [2.2.13 SMB2 CREATE Request]
///
/// [2.2.13 SMB2 CREATE Request]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e8fb45c1-a03d-44ca-b7ae-47385cfd7997
#[derive(Debug, Clone)]
pub struct CreateOptions: u32 {
const FILE_DIRECTORY_FILE = 0x00000001;
const FILE_WRITE_THROUGH = 0x00000002;
const FILE_SEQUENTIAL_ONLY = 0x00000004;
const FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008;
const FILE_SYNCHRONOUS_IO_ALERT = 0x00000010;
const FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020;
const FILE_NON_DIRECTORY_FILE = 0x00000040;
const FILE_COMPLETE_IF_OPLOCKED = 0x00000100;
const FILE_NO_EA_KNOWLEDGE = 0x00000200;
const FILE_RANDOM_ACCESS = 0x00000800;
const FILE_DELETE_ON_CLOSE = 0x00001000;
const FILE_OPEN_BY_FILE_ID = 0x00002000;
const FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000;
const FILE_NO_COMPRESSION = 0x00008000;
const FILE_OPEN_REMOTE_INSTANCE = 0x00000400;
const FILE_OPEN_REQUIRING_OPLOCK = 0x00010000;
const FILE_DISALLOW_EXCLUSIVE = 0x00020000;
const FILE_RESERVE_OPFILTER = 0x00100000;
const FILE_OPEN_REPARSE_POINT = 0x00200000;
const FILE_OPEN_NO_RECALL = 0x00400000;
const FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000;
}
}
/// [2.2.1.5.1 Device Create Response (DR_CREATE_RSP)]
///
/// [2.2.1.5.1 Device Create Response (DR_CREATE_RSP)]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/99e5fca5-b37a-41e4-bc69-8d7da7860f76
#[derive(Debug)]
pub struct DeviceCreateResponse {
pub device_io_reply: DeviceIoResponse,
pub file_id: u32,
pub information: Information,
}
impl DeviceCreateResponse {
const NAME: &str = "DR_CREATE_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_reply.encode(dst)?;
dst.write_u32(self.file_id);
dst.write_u8(self.information.bits());
Ok(())
}
pub fn size(&self) -> usize {
self.device_io_reply.size() // DeviceIoReply
+ 4 // FileId
+ 1 // Information
}
}
bitflags! {
/// Defined in [2.2.1.5.1 Device Create Response (DR_CREATE_RSP)]
///
/// [2.2.1.5.1 Device Create Response (DR_CREATE_RSP)]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/99e5fca5-b37a-41e4-bc69-8d7da7860f76
#[derive(Debug)]
pub struct Information: u8 {
/// A new file was created.
const FILE_SUPERSEDED = 0x00000000;
/// An existing file was opened.
const FILE_OPENED = 0x00000001;
/// An existing file was overwritten.
const FILE_OVERWRITTEN = 0x00000003;
}
}
+21 -2
View File
@@ -6,7 +6,7 @@ use ironrdp_pdu::{ensure_size, invalid_message_err, PduDecode, PduEncode, PduErr
use self::efs::{
ClientDeviceListAnnounce, ClientNameRequest, CoreCapability, CoreCapabilityKind, DeviceControlResponse,
DeviceIoRequest, ServerDeviceAnnounceResponse, VersionAndIdPdu, VersionAndIdPduKind,
DeviceCreateResponse, DeviceIoRequest, ServerDeviceAnnounceResponse, VersionAndIdPdu, VersionAndIdPduKind,
};
pub mod efs;
@@ -21,6 +21,7 @@ pub enum RdpdrPdu {
ServerDeviceAnnounceResponse(ServerDeviceAnnounceResponse),
DeviceIoRequest(DeviceIoRequest),
DeviceControlResponse(DeviceControlResponse),
DeviceCreateResponse(DeviceCreateResponse),
/// TODO: temporary value for development, this should be removed
Unimplemented,
}
@@ -69,7 +70,7 @@ impl RdpdrPdu {
component: Component::RdpdrCtypCore,
packet_id: PacketId::CoreDeviceIoRequest,
},
RdpdrPdu::DeviceControlResponse(_) => SharedHeader {
RdpdrPdu::DeviceControlResponse(_) | RdpdrPdu::DeviceCreateResponse(_) => SharedHeader {
component: Component::RdpdrCtypCore,
packet_id: PacketId::CoreDeviceIoCompletion,
},
@@ -109,6 +110,7 @@ impl PduEncode for RdpdrPdu {
RdpdrPdu::ServerDeviceAnnounceResponse(pdu) => pdu.encode(dst),
RdpdrPdu::DeviceIoRequest(pdu) => pdu.encode(dst),
RdpdrPdu::DeviceControlResponse(pdu) => pdu.encode(dst),
RdpdrPdu::DeviceCreateResponse(pdu) => pdu.encode(dst),
RdpdrPdu::Unimplemented => Ok(()),
}
}
@@ -122,6 +124,7 @@ impl PduEncode for RdpdrPdu {
RdpdrPdu::ServerDeviceAnnounceResponse(pdu) => pdu.name(),
RdpdrPdu::DeviceIoRequest(pdu) => pdu.name(),
RdpdrPdu::DeviceControlResponse(pdu) => pdu.name(),
RdpdrPdu::DeviceCreateResponse(pdu) => pdu.name(),
RdpdrPdu::Unimplemented => "Unimplemented",
}
}
@@ -136,6 +139,7 @@ impl PduEncode for RdpdrPdu {
RdpdrPdu::ServerDeviceAnnounceResponse(pdu) => pdu.size(),
RdpdrPdu::DeviceIoRequest(pdu) => pdu.size(),
RdpdrPdu::DeviceControlResponse(pdu) => pdu.size(),
RdpdrPdu::DeviceCreateResponse(pdu) => pdu.size(),
RdpdrPdu::Unimplemented => 0,
}
}
@@ -165,6 +169,9 @@ impl fmt::Debug for RdpdrPdu {
Self::DeviceControlResponse(it) => {
write!(f, "RdpdrPdu({:?})", it)
}
Self::DeviceCreateResponse(it) => {
write!(f, "RdpdrPdu({:?})", it)
}
Self::Unimplemented => {
write!(f, "RdpdrPdu::Unimplemented")
}
@@ -172,6 +179,18 @@ impl fmt::Debug for RdpdrPdu {
}
}
impl From<DeviceControlResponse> for RdpdrPdu {
fn from(value: DeviceControlResponse) -> Self {
Self::DeviceControlResponse(value)
}
}
impl From<DeviceCreateResponse> for RdpdrPdu {
fn from(value: DeviceCreateResponse) -> Self {
Self::DeviceCreateResponse(value)
}
}
/// [2.2.1.1 Shared Header (RDPDR_HEADER)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/29d4108f-8163-4a67-8271-e48c4b9c2a7c)
/// A header that is shared by all RDPDR PDUs.
#[derive(Debug)]
-1
View File
@@ -45,7 +45,6 @@ const EXTRA_LINTS: &[&str] = &[
"clippy::string_to_string",
// TODO: "clippy::std_instead_of_alloc",
// TODO: "clippy::std_instead_of_core",
"clippy::unreadable_literal",
"clippy::separated_literal_suffix",
"clippy::unused_self",
// TODO: "clippy::use_self", // NOTE(@CBenoit): not sure about that one