rdp/core/
gcc.rs

1use model::data::{Component, U32, U16, Trame, to_vec, Message, DataType, DynOption, MessageOption, Check, Array};
2use model::unicode::Unicode;
3use model::error::{RdpResult, RdpError, RdpErrorKind, Error};
4use core::per;
5use std::io::{Cursor, Read};
6use std::collections::HashMap;
7
8
9const T124_02_98_OID: [u8; 6] = [ 0, 0, 20, 124, 0, 1 ];
10const H221_CS_KEY: [u8; 4] = *b"Duca";
11const H221_SC_KEY: [u8; 4] = *b"McDn";
12/// RDP protocol version
13/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/00f1da4a-ee9c-421a-852f-c19f92343d73?redirectedfrom=MSDN
14#[repr(u32)]
15#[allow(dead_code)]
16#[derive(Copy, Clone, Eq, PartialEq)]
17pub enum Version {
18    RdpVersion = 0x00080001,
19    RdpVersion5plus = 0x00080004,
20    Unknown
21}
22
23impl From<u32> for Version {
24    fn from(e: u32) -> Self {
25        match e {
26            0x00080001 => Version::RdpVersion5plus,
27            0x00080004 => Version::RdpVersion,
28            _ => Version::Unknown
29        }
30    }
31}
32
33/// Color depth
34/// This flag is deprecated
35/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/00f1da4a-ee9c-421a-852f-c19f92343d73?redirectedfrom=MSDN
36#[repr(u16)]
37#[allow(dead_code)]
38enum ColorDepth {
39    RnsUdColor8BPP = 0xCA01,
40    RnsUdColor16BPP555 = 0xCA02,
41    RnsUdColor16BPP565 = 0xCA03,
42    RnsUdColor24BPP = 0xCA04
43}
44
45#[repr(u16)]
46enum Sequence {
47    RnsUdSasDel = 0xAA03
48}
49
50/// Keyboard layout
51/// https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766503(v=ws.10)?redirectedfrom=MSDN
52#[repr(u32)]
53#[derive(Copy, Clone)]
54pub enum KeyboardLayout {
55    Arabic = 0x00000401,
56    Bulgarian = 0x00000402,
57    ChineseUsKeyboard = 0x00000404,
58    Czech = 0x00000405,
59    Danish = 0x00000406,
60    German = 0x00000407,
61    Greek = 0x00000408,
62    US = 0x00000409,
63    Spanish = 0x0000040a,
64    Finnish = 0x0000040b,
65    French = 0x0000040c,
66    Hebrew = 0x0000040d,
67    Hungarian = 0x0000040e,
68    Icelandic = 0x0000040f,
69    Italian = 0x00000410,
70    Japanese = 0x00000411,
71    Korean = 0x00000412,
72    Dutch = 0x00000413,
73    Norwegian = 0x00000414
74}
75
76/// Keyboard type
77/// Ibm101102Keys is the most common keyboard type
78#[repr(u32)]
79#[allow(dead_code)]
80pub enum KeyboardType {
81    IbmPcXt83Key  = 0x00000001,
82    Olivetti  = 0x00000002,
83    IbmPcAt84Key  = 0x00000003,
84    Ibm101102Keys  = 0x00000004,
85    Nokia1050  = 0x00000005,
86    Nokia9140  = 0x00000006,
87    Japanese  = 0x00000007
88}
89
90#[repr(u16)]
91#[allow(dead_code)]
92enum HighColor {
93    HighColor4BPP = 0x0004,
94    HighColor8BPP = 0x0008,
95    HighColor15BPP = 0x000f,
96    HighColor16BPP = 0x0010,
97    HighColor24BPP = 0x0018
98}
99
100
101/// Supported color depth
102/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/00f1da4a-ee9c-421a-852f-c19f92343d73?redirectedfrom=MSDN
103#[repr(u16)]
104#[allow(dead_code)]
105enum Support {
106    RnsUd24BPPSupport = 0x0001,
107    RnsUd16BPPSupport = 0x0002,
108    RnsUd15BPPSupport = 0x0004,
109    RnsUd32BPPSupport = 0x0008
110}
111
112/// Negotiation of some capability for pdu layer
113/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/00f1da4a-ee9c-421a-852f-c19f92343d73?redirectedfrom=MSDN
114#[repr(u16)]
115#[allow(dead_code)]
116enum CapabilityFlag {
117    RnsUdCsSupportErrinfoPDU = 0x0001,
118    RnsUdCsWant32BPPSession = 0x0002,
119    RnsUdCsSupportStatusInfoPdu = 0x0004,
120    RnsUdCsStrongAsymmetricKeys  = 0x0008,
121    RnsUdCsUnused = 0x0010,
122    RnsUdCsValidConnectionType = 0x0020,
123    RnsUdCsSupportMonitorLayoutPDU = 0x0040,
124    RnsUdCsSupportNetcharAutodetect = 0x0080,
125    RnsUdCsSupportDynvcGFXProtocol = 0x0100,
126    RnsUdCsSupportDynamicTimezone = 0x0200,
127    RnsUdCsSupportHeartbeatPDU = 0x0400
128}
129
130/// Supported encryption method
131/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/6b58e11e-a32b-4903-b736-339f3cfe46ec?redirectedfrom=MSDN
132#[repr(u32)]
133#[allow(dead_code)]
134enum EncryptionMethod {
135    EncryptionFlag40bit = 0x00000001,
136    EncryptionFlag128bit = 0x00000002,
137    EncryptionFlag56bit = 0x00000008,
138    FipsEncryptionFlag = 0x00000010
139}
140
141/// Encryption level
142/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/3e86b68d-3e2e-4433-b486-878875778f4b?redirectedfrom=MSDN
143#[allow(dead_code)]
144enum EncryptionLevel {
145    None = 0x00000000,
146    Low = 0x00000001,
147    ClientCompatible = 0x00000002,
148    High = 0x00000003,
149    Fips = 0x00000004
150}
151
152#[repr(u16)]
153#[derive(Eq, PartialEq, Hash)]
154pub enum MessageType  {
155    //server -> client
156    ScCore = 0x0C01,
157    ScSecurity = 0x0C02,
158    ScNet = 0x0C03,
159    //client -> server
160    CsCore = 0xC001,
161    CsSecurity = 0xC002,
162    CsNet = 0xC003,
163    CsCluster = 0xC004,
164    CsMonitor = 0xC005,
165    Unknown = 0
166}
167
168impl From<u16> for MessageType {
169    fn from(e: u16) -> Self {
170        match e {
171            0x0C01 => MessageType::ScCore,
172            0x0C02 => MessageType::ScSecurity,
173            0x0C03 => MessageType::ScNet,
174            0xC001 => MessageType::CsCore,
175            0xC002 => MessageType::CsSecurity,
176            0xC003 => MessageType::CsNet,
177            0xC004 => MessageType::CsCluster,
178            0xC005 => MessageType::CsMonitor,
179            _ => MessageType::Unknown
180        }
181    }
182}
183
184/// In case of client
185/// This is all mandatory fields need by client core data
186#[derive(Clone)]
187pub struct ClientData {
188    pub width: u16,
189    pub height: u16,
190    pub layout: KeyboardLayout,
191    pub server_selected_protocol: u32,
192    pub rdp_version: Version,
193    pub name: String
194}
195
196/// This is the first client specific data
197///
198/// This field are obsolete and for modern
199/// RDP they are not use
200/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/00f1da4a-ee9c-421a-852f-c19f92343d73?redirectedfrom=MSDN
201pub fn client_core_data(parameter: Option<ClientData>) -> Component {
202    let client_parameter = parameter.unwrap_or(
203        ClientData {
204            width: 0,
205            height: 0,
206            layout: KeyboardLayout::French,
207            server_selected_protocol: 0,
208            rdp_version: Version::RdpVersion5plus,
209            name: "".to_string()
210        });
211
212    let client_name = if client_parameter.name.len() >= 16 {
213        (&client_parameter.name[0..16]).to_string()
214    } else {
215        client_parameter.name.clone() + &"\x00".repeat(16 - client_parameter.name.len())
216    };
217
218    component![
219        "version" => U32::LE(client_parameter.rdp_version as u32),
220        "desktopWidth" => U16::LE(client_parameter.width),
221        "desktopHeight" => U16::LE(client_parameter.height),
222        "colorDepth" => U16::LE(ColorDepth::RnsUdColor8BPP as u16),
223        "sasSequence" => U16::LE(Sequence::RnsUdSasDel as u16),
224        "kbdLayout" => U32::LE(client_parameter.layout as u32),
225        "clientBuild" => U32::LE(3790),
226        "clientName" => client_name.to_string().to_unicode(),
227        "keyboardType" => U32::LE(KeyboardType::Ibm101102Keys as u32),
228        "keyboardSubType" => U32::LE(0),
229        "keyboardFnKeys" => U32::LE(12),
230        "imeFileName" => vec![0 as u8; 64],
231        "postBeta2ColorDepth" => U16::LE(ColorDepth::RnsUdColor8BPP as u16),
232        "clientProductId" => U16::LE(1),
233        "serialNumber" => U32::LE(0),
234        "highColorDepth" => U16::LE(HighColor::HighColor24BPP as u16),
235        "supportedColorDepths" => U16::LE(
236            //Support::RnsUd15BPPSupport as u16 |
237            Support::RnsUd16BPPSupport as u16 |
238            //Support::RnsUd24BPPSupport as u16 |
239            Support::RnsUd32BPPSupport as u16
240            ),
241        "earlyCapabilityFlags" => U16::LE(CapabilityFlag::RnsUdCsSupportErrinfoPDU as u16),
242        "clientDigProductId" => vec![0; 64],
243        "connectionType" => 0 as u8,
244        "pad1octet" => 0 as u8,
245        "serverSelectedProtocol" => U32::LE(client_parameter.server_selected_protocol)
246    ]
247}
248
249pub fn server_core_data() -> Component{
250    component![
251        "rdpVersion" => U32::LE(0),
252        "clientRequestedProtocol" => Some(U32::LE(0)),
253        "earlyCapabilityFlags" => Some(U32::LE(0))
254    ]
255}
256
257/// Client security releated to deprecated RDP security layer
258/// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/6b58e11e-a32b-4903-b736-339f3cfe46ec?redirectedfrom=MSDN
259pub fn client_security_data() -> Component {
260    component![
261        "encryptionMethods" => U32::LE(
262            EncryptionMethod::EncryptionFlag40bit as u32 |
263            EncryptionMethod::EncryptionFlag56bit as u32 |
264            EncryptionMethod::EncryptionFlag128bit as u32
265         ),
266        "extEncryptionMethods" => U32::LE(0)
267    ]
268}
269
270/// In case of non ssl security layer
271/// we need to check data in this packet
272pub fn server_security_data() -> Component {
273    component![
274        "encryptionMethod" => U32::LE(0),
275        "encryptionLevel" => U32::LE(0)
276    ]
277}
278
279/// Actually we have no more classic channel
280pub fn channel_def(name: &String, options: u32) -> Component {
281    component![
282        "name"=> name.as_bytes().to_vec(),
283        "options" => U32::LE(options)
284    ]
285}
286
287/// Actually we have no more channel than the classic one
288pub fn client_network_data(channel_def_array: Trame) -> Component {
289    component![
290        "channelCount" => U32::LE(channel_def_array.len() as u32),
291        "channelDefArray" => to_vec(&channel_def_array)
292    ]
293}
294
295pub fn server_network_data() -> Component {
296    component![
297        "MCSChannelId" => Check::new(U16::LE(1003)),
298        "channelCount" => DynOption::new(U16::LE(0), |count| MessageOption::Size("channelIdArray".to_string(), count.inner() as usize * 2)),
299        "channelIdArray" => Array::new(|| U16::LE(0))
300    ]
301}
302
303pub fn block_header(data_type: Option<MessageType>, length: Option<u16>) -> Component {
304    component![
305        "type" => U16::LE(data_type.unwrap_or(MessageType::CsCore) as u16),
306        "length" => U16::LE(length.unwrap_or(0) as u16 + 4)
307    ]
308}
309
310pub fn write_conference_create_request(user_data: &[u8]) ->RdpResult<Vec<u8>> {
311    let mut result = Cursor::new(vec![]);
312    per::write_choice(0, &mut result)?;
313    per::write_object_identifier(&T124_02_98_OID, &mut result)?;
314    per::write_length(user_data.len() as u16 + 14)?.write(&mut result)?;
315    per::write_choice(0, &mut result)?;
316    per::write_selection(0x08, &mut result)?;
317    per::write_numeric_string(b"1", 1, &mut result)?;
318    per::write_padding(1, &mut result)?;
319    per::write_number_of_set(1, &mut result)?;
320    per::write_choice(0xc0, &mut result)?;
321    per::write_octet_stream(&H221_CS_KEY, 4,&mut result)?;
322    per::write_octet_stream(user_data, 0, &mut result)?;
323    Ok(result.into_inner())
324}
325
326pub struct ServerData {
327    pub channel_ids: Vec<u16>,
328    pub rdp_version : Version
329}
330
331/// Read conference create response
332pub fn read_conference_create_response(cc_response: &mut dyn Read) -> RdpResult<ServerData> {
333    per::read_choice(cc_response)?;
334    per::read_object_identifier(&T124_02_98_OID, cc_response)?;
335    per::read_length(cc_response)?;
336    per::read_choice(cc_response)?;
337    per::read_integer_16(1001, cc_response)?;
338    per::read_integer(cc_response)?;
339    per::read_enumerates(cc_response)?;
340    per::read_number_of_set(cc_response)?;
341    per::read_choice(cc_response)?;
342    per::read_octet_stream(&H221_SC_KEY, 4, cc_response)?;
343
344    let length = per::read_length(cc_response)?;
345    let mut result = HashMap::new();
346    let mut sub = cc_response.take(length as u64);
347    loop {
348
349        let mut header = block_header(None, None);
350        // No more blocks to read
351        if header.read(&mut sub).is_err() {
352            break;
353        }
354
355        let mut buffer = vec![0 as u8; (cast!(DataType::U16, header["length"])? - header.length() as u16) as usize];
356        sub.read_exact(&mut buffer)?;
357
358        match MessageType::from(cast!(DataType::U16, header["type"])?) {
359            MessageType::ScCore => {
360                let mut server_core = server_core_data();
361                server_core.read(&mut Cursor::new(buffer))?;
362                result.insert(MessageType::ScCore, server_core);
363            },
364            MessageType::ScSecurity => {
365                let mut server_security = server_security_data();
366                server_security.read(&mut Cursor::new(buffer))?;
367                result.insert(MessageType::ScSecurity, server_security);
368            },
369            MessageType::ScNet => {
370                let mut server_net = server_network_data();
371                server_net.read(&mut Cursor::new(buffer))?;
372                result.insert(MessageType::ScNet, server_net);
373            }
374            _ => println!("GCC: Unknown server block {:?}", cast!(DataType::U16, header["type"])?)
375        }
376    }
377
378    // All section are important
379    Ok(ServerData{
380        channel_ids: cast!(DataType::Trame, result[&MessageType::ScNet]["channelIdArray"])?.into_iter().map(|x| cast!(DataType::U16, x).unwrap()).collect(),
381        rdp_version: Version::from(cast!(DataType::U32, result[&MessageType::ScCore]["rdpVersion"])?)
382    })
383}