ironrdp_pdu/
gcc.rs

1use std::io;
2
3use ironrdp_core::{
4    cast_length, decode, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeErrorKind, DecodeResult,
5    Encode, EncodeResult, ReadCursor, WriteCursor,
6};
7use num_derive::{FromPrimitive, ToPrimitive};
8use num_traits::{FromPrimitive, ToPrimitive};
9use thiserror::Error;
10
11use crate::PduError;
12
13pub mod conference_create;
14
15mod cluster_data;
16mod core_data;
17mod message_channel_data;
18mod monitor_data;
19mod monitor_extended_data;
20mod multi_transport_channel_data;
21mod network_data;
22mod security_data;
23
24pub use self::cluster_data::{ClientClusterData, ClusterDataError, RedirectionFlags, RedirectionVersion};
25pub use self::conference_create::{ConferenceCreateRequest, ConferenceCreateResponse};
26pub use self::core_data::client::{
27    ClientColorDepth, ClientCoreData, ClientCoreOptionalData, ClientEarlyCapabilityFlags, ColorDepth, ConnectionType,
28    HighColorDepth, KeyboardType, SecureAccessSequence, SupportedColorDepths, IME_FILE_NAME_SIZE,
29};
30pub use self::core_data::server::{ServerCoreData, ServerCoreOptionalData, ServerEarlyCapabilityFlags};
31pub use self::core_data::{CoreDataError, RdpVersion};
32pub use self::message_channel_data::{ClientMessageChannelData, ServerMessageChannelData};
33pub use self::monitor_data::{
34    ClientMonitorData, Monitor, MonitorFlags, MONITOR_COUNT_SIZE, MONITOR_FLAGS_SIZE, MONITOR_SIZE,
35};
36pub use self::monitor_extended_data::{ClientMonitorExtendedData, ExtendedMonitorInfo, MonitorOrientation};
37pub use self::multi_transport_channel_data::{MultiTransportChannelData, MultiTransportFlags};
38pub use self::network_data::{
39    ChannelDef, ChannelName, ChannelOptions, ClientNetworkData, NetworkDataError, ServerNetworkData,
40};
41pub use self::security_data::{
42    ClientSecurityData, EncryptionLevel, EncryptionMethod, SecurityDataError, ServerSecurityData,
43};
44
45macro_rules! user_header_try {
46    ($e:expr) => {
47        match $e {
48            Ok(user_header) => user_header,
49            Err(e) if matches!(e.kind(), DecodeErrorKind::NotEnoughBytes { .. }) => break,
50            Err(e) => return Err(e),
51        }
52    };
53}
54
55const USER_DATA_HEADER_SIZE: usize = 4;
56
57/// 2.2.1.3 Client MCS Connect Initial PDU with GCC Conference Create Request
58///
59/// [2.2.1.3]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/db6713ee-1c0e-4064-a3b3-0fac30b4037b
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub struct ClientGccBlocks {
62    pub core: ClientCoreData,
63    pub security: ClientSecurityData,
64    /// According to [MSDN](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/c1bea8bd-069c-4437-9769-db5d27935225),
65    /// the Client GCC blocks MUST contain Core, Security, Network GCC blocks.
66    /// But the FreeRDP does not send the Network GCC block if it does not have channels to join,
67    /// and what is surprising - Windows RDP server accepts this GCC block.
68    /// Because of this, the Network GCC block is made optional in IronRDP.
69    pub network: Option<ClientNetworkData>,
70    pub cluster: Option<ClientClusterData>,
71    pub monitor: Option<ClientMonitorData>,
72    pub message_channel: Option<ClientMessageChannelData>,
73    pub multi_transport_channel: Option<MultiTransportChannelData>,
74    pub monitor_extended: Option<ClientMonitorExtendedData>,
75}
76
77impl ClientGccBlocks {
78    const NAME: &'static str = "ClientGccBlocks";
79
80    pub fn channel_names(&self) -> Option<Vec<ChannelDef>> {
81        self.network.as_ref().map(|network| network.channels.clone())
82    }
83}
84
85impl Encode for ClientGccBlocks {
86    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
87        ensure_size!(in: dst, size: self.size());
88
89        UserDataHeader::encode(dst, ClientGccType::CoreData, &self.core)?;
90        UserDataHeader::encode(dst, ClientGccType::SecurityData, &self.security)?;
91
92        if let Some(ref network) = self.network {
93            UserDataHeader::encode(dst, ClientGccType::NetworkData, network)?;
94        }
95        if let Some(ref cluster) = self.cluster {
96            UserDataHeader::encode(dst, ClientGccType::ClusterData, cluster)?;
97        }
98        if let Some(ref monitor) = self.monitor {
99            UserDataHeader::encode(dst, ClientGccType::MonitorData, monitor)?;
100        }
101        if let Some(ref message_channel) = self.message_channel {
102            UserDataHeader::encode(dst, ClientGccType::MessageChannelData, message_channel)?;
103        }
104        if let Some(ref multi_transport_channel) = self.multi_transport_channel {
105            UserDataHeader::encode(dst, ClientGccType::MultiTransportChannelData, multi_transport_channel)?;
106        }
107        if let Some(ref monitor_extended) = self.monitor_extended {
108            UserDataHeader::encode(dst, ClientGccType::MonitorExtendedData, monitor_extended)?;
109        }
110
111        Ok(())
112    }
113
114    fn name(&self) -> &'static str {
115        Self::NAME
116    }
117
118    fn size(&self) -> usize {
119        let mut size = self.core.size() + self.security.size() + USER_DATA_HEADER_SIZE * 2;
120
121        if let Some(ref network) = self.network {
122            size += network.size() + USER_DATA_HEADER_SIZE;
123        }
124        if let Some(ref cluster) = self.cluster {
125            size += cluster.size() + USER_DATA_HEADER_SIZE;
126        }
127        if let Some(ref monitor) = self.monitor {
128            size += monitor.size() + USER_DATA_HEADER_SIZE;
129        }
130        if let Some(ref message_channel) = self.message_channel {
131            size += message_channel.size() + USER_DATA_HEADER_SIZE;
132        }
133        if let Some(ref multi_transport_channel) = self.multi_transport_channel {
134            size += multi_transport_channel.size() + USER_DATA_HEADER_SIZE;
135        }
136        if let Some(ref monitor_extended) = self.monitor_extended {
137            size += monitor_extended.size() + USER_DATA_HEADER_SIZE;
138        }
139
140        size
141    }
142}
143
144impl<'de> Decode<'de> for ClientGccBlocks {
145    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
146        let mut core = None;
147        let mut security = None;
148        let mut network = None;
149        let mut cluster = None;
150        let mut monitor = None;
151        let mut message_channel = None;
152        let mut multi_transport_channel = None;
153        let mut monitor_extended = None;
154
155        loop {
156            let (ty, cur) = user_header_try!(UserDataHeader::decode(src));
157
158            match ty {
159                ClientGccType::CoreData => core = Some(decode(cur)?),
160                ClientGccType::SecurityData => security = Some(decode(cur)?),
161                ClientGccType::NetworkData => network = Some(decode(cur)?),
162                ClientGccType::ClusterData => cluster = Some(decode(cur)?),
163                ClientGccType::MonitorData => monitor = Some(decode(cur)?),
164                ClientGccType::MessageChannelData => message_channel = Some(decode(cur)?),
165                ClientGccType::MonitorExtendedData => monitor_extended = Some(decode(cur)?),
166                ClientGccType::MultiTransportChannelData => multi_transport_channel = Some(decode(cur)?),
167            };
168        }
169
170        Ok(Self {
171            core: core.ok_or_else(|| invalid_field_err!("core", "required GCC core is absent"))?,
172            security: security.ok_or_else(|| invalid_field_err!("security", "required GCC security is absent"))?,
173            network,
174            cluster,
175            monitor,
176            message_channel,
177            multi_transport_channel,
178            monitor_extended,
179        })
180    }
181}
182
183#[derive(Debug, Clone, PartialEq, Eq)]
184pub struct ServerGccBlocks {
185    pub core: ServerCoreData,
186    pub network: ServerNetworkData,
187    pub security: ServerSecurityData,
188    pub message_channel: Option<ServerMessageChannelData>,
189    pub multi_transport_channel: Option<MultiTransportChannelData>,
190}
191
192impl ServerGccBlocks {
193    const NAME: &'static str = "ServerGccBlocks";
194
195    pub fn channel_ids(&self) -> Vec<u16> {
196        self.network.channel_ids.clone()
197    }
198    pub fn global_channel_id(&self) -> u16 {
199        self.network.io_channel
200    }
201}
202
203impl Encode for ServerGccBlocks {
204    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
205        UserDataHeader::encode(dst, ServerGccType::CoreData, &self.core)?;
206        UserDataHeader::encode(dst, ServerGccType::NetworkData, &self.network)?;
207        UserDataHeader::encode(dst, ServerGccType::SecurityData, &self.security)?;
208
209        if let Some(ref message_channel) = self.message_channel {
210            UserDataHeader::encode(dst, ServerGccType::MessageChannelData, message_channel)?;
211        }
212        if let Some(ref multi_transport_channel) = self.multi_transport_channel {
213            UserDataHeader::encode(dst, ServerGccType::MultiTransportChannelData, multi_transport_channel)?;
214        }
215
216        Ok(())
217    }
218
219    fn name(&self) -> &'static str {
220        Self::NAME
221    }
222
223    fn size(&self) -> usize {
224        let mut size = self.core.size() + self.network.size() + self.security.size() + USER_DATA_HEADER_SIZE * 3;
225
226        if let Some(ref message_channel) = self.message_channel {
227            size += message_channel.size() + USER_DATA_HEADER_SIZE;
228        }
229        if let Some(ref multi_transport_channel) = self.multi_transport_channel {
230            size += multi_transport_channel.size() + USER_DATA_HEADER_SIZE;
231        }
232
233        size
234    }
235}
236
237impl<'de> Decode<'de> for ServerGccBlocks {
238    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
239        let mut core = None;
240        let mut network = None;
241        let mut security = None;
242        let mut message_channel = None;
243        let mut multi_transport_channel = None;
244
245        loop {
246            let (ty, cur) = user_header_try!(UserDataHeader::decode(src));
247
248            match ty {
249                ServerGccType::CoreData => core = Some(decode(cur)?),
250                ServerGccType::NetworkData => network = Some(decode(cur)?),
251                ServerGccType::SecurityData => security = Some(decode(cur)?),
252                ServerGccType::MessageChannelData => message_channel = Some(decode(cur)?),
253                ServerGccType::MultiTransportChannelData => multi_transport_channel = Some(decode(cur)?),
254            };
255        }
256
257        Ok(Self {
258            core: core.ok_or_else(|| invalid_field_err!("core", "required GCC core is absent"))?,
259            network: network.ok_or_else(|| invalid_field_err!("network", "required GCC network is absent"))?,
260            security: security.ok_or_else(|| invalid_field_err!("security", "required GCC security is absent"))?,
261            message_channel,
262            multi_transport_channel,
263        })
264    }
265}
266
267#[repr(u16)]
268#[derive(Debug, Copy, Clone, FromPrimitive, ToPrimitive)]
269pub enum ClientGccType {
270    CoreData = 0xC001,
271    SecurityData = 0xC002,
272    NetworkData = 0xC003,
273    ClusterData = 0xC004,
274    MonitorData = 0xC005,
275    MessageChannelData = 0xC006,
276    MonitorExtendedData = 0xC008,
277    MultiTransportChannelData = 0xC00A,
278}
279
280#[repr(u16)]
281#[derive(Debug, Copy, Clone, FromPrimitive, ToPrimitive)]
282pub enum ServerGccType {
283    CoreData = 0x0C01,
284    SecurityData = 0x0C02,
285    NetworkData = 0x0C03,
286    MessageChannelData = 0x0C04,
287    MultiTransportChannelData = 0x0C08,
288}
289
290#[derive(Debug)]
291pub struct UserDataHeader;
292
293impl UserDataHeader {
294    const FIXED_PART_SIZE: usize = 2 /* blockType */ + 2 /* blockLen */;
295
296    pub fn encode<T, B>(dst: &mut WriteCursor<'_>, block_type: T, block: &B) -> EncodeResult<()>
297    where
298        T: ToPrimitive,
299        B: Encode,
300    {
301        ensure_fixed_part_size!(in: dst);
302
303        dst.write_u16(block_type.to_u16().unwrap());
304        dst.write_u16(cast_length!("blockLen", block.size() + USER_DATA_HEADER_SIZE)?);
305        block.encode(dst)?;
306
307        Ok(())
308    }
309
310    pub fn decode<'de, T>(src: &mut ReadCursor<'de>) -> DecodeResult<(T, &'de [u8])>
311    where
312        T: FromPrimitive,
313    {
314        ensure_fixed_part_size!(in: src);
315
316        let block_type =
317            T::from_u16(src.read_u16()).ok_or_else(|| invalid_field_err!("blockType", "invalid GCC type"))?;
318        let block_length: usize = cast_length!("blockLen", src.read_u16())?;
319
320        if block_length <= USER_DATA_HEADER_SIZE {
321            return Err(invalid_field_err!("blockLen", "invalid UserDataHeader length"));
322        }
323
324        let len = block_length - USER_DATA_HEADER_SIZE;
325        ensure_size!(in: src, size: len);
326
327        Ok((block_type, src.read_slice(len)))
328    }
329}
330
331#[derive(Debug, Error)]
332pub enum GccError {
333    #[error("IO error")]
334    IOError(#[from] io::Error),
335    #[error("core data block error")]
336    CoreError(#[from] CoreDataError),
337    #[error("security data block error")]
338    SecurityError(#[from] SecurityDataError),
339    #[error("network data block error")]
340    NetworkError(#[from] NetworkDataError),
341    #[error("cluster data block error")]
342    ClusterError(#[from] ClusterDataError),
343    #[error("invalid GCC block type")]
344    InvalidGccType,
345    #[error("invalid conference create request: {0}")]
346    InvalidConferenceCreateRequest(String),
347    #[error("invalid Conference create response: {0}")]
348    InvalidConferenceCreateResponse(String),
349    #[error("a server did not send the required GCC data block: {0:?}")]
350    RequiredClientDataBlockIsAbsent(ClientGccType),
351    #[error("a client did not send the required GCC data block: {0:?}")]
352    RequiredServerDataBlockIsAbsent(ServerGccType),
353    #[error("PDU error: {0}")]
354    Pdu(PduError),
355}
356
357impl From<PduError> for GccError {
358    fn from(e: PduError) -> Self {
359        Self::Pdu(e)
360    }
361}