ironrdp_pdu/rdp/
server_license.rs

1use std::io;
2
3use bitflags::bitflags;
4use ironrdp_core::{
5    cast_length, ensure_fixed_part_size, invalid_field_err, unsupported_value_err, Decode, DecodeResult, Encode,
6    EncodeResult, ReadCursor, WriteCursor,
7};
8use md5::Digest as _;
9use num_derive::{FromPrimitive, ToPrimitive};
10use num_traits::{FromPrimitive as _, ToPrimitive as _};
11use thiserror::Error;
12
13use crate::rdp::headers::{BasicSecurityHeader, BasicSecurityHeaderFlags, BASIC_SECURITY_HEADER_SIZE};
14pub use crate::rdp::server_license::client_license_info::ClientLicenseInfo;
15use crate::PduError;
16
17#[cfg(test)]
18mod tests;
19
20mod client_license_info;
21mod client_new_license_request;
22mod client_platform_challenge_response;
23mod licensing_error_message;
24mod server_license_request;
25mod server_platform_challenge;
26mod server_upgrade_license;
27
28pub use self::client_new_license_request::{ClientNewLicenseRequest, PLATFORM_ID};
29pub use self::client_platform_challenge_response::{
30    ClientHardwareIdentification, ClientPlatformChallengeResponse, PlatformChallengeResponseData,
31};
32pub use self::licensing_error_message::{LicenseErrorCode, LicensingErrorMessage, LicensingStateTransition};
33pub use self::server_license_request::{cert, ProductInfo, Scope, ServerCertificate, ServerLicenseRequest};
34pub use self::server_platform_challenge::ServerPlatformChallenge;
35pub use self::server_upgrade_license::{LicenseInformation, ServerUpgradeLicense};
36
37pub const PREAMBLE_SIZE: usize = 4;
38pub const PREMASTER_SECRET_SIZE: usize = 48;
39pub const RANDOM_NUMBER_SIZE: usize = 32;
40
41const PROTOCOL_VERSION_MASK: u8 = 0x0F;
42
43const BLOB_TYPE_SIZE: usize = 2;
44const BLOB_LENGTH_SIZE: usize = 2;
45
46const UTF8_NULL_TERMINATOR_SIZE: usize = 1;
47const UTF16_NULL_TERMINATOR_SIZE: usize = 2;
48
49const KEY_EXCHANGE_ALGORITHM_RSA: u32 = 1;
50
51const MAC_SIZE: usize = 16;
52
53#[derive(Debug, PartialEq, Eq, Clone, Default)]
54pub struct LicenseEncryptionData {
55    pub premaster_secret: Vec<u8>,
56    pub mac_salt_key: Vec<u8>,
57    pub license_key: Vec<u8>,
58}
59
60#[derive(Debug, PartialEq, Eq)]
61pub struct LicenseHeader {
62    pub security_header: BasicSecurityHeader,
63    pub preamble_message_type: PreambleType,
64    pub preamble_flags: PreambleFlags,
65    pub preamble_version: PreambleVersion,
66    pub preamble_message_size: u16,
67}
68
69impl LicenseHeader {
70    const NAME: &'static str = "LicenseHeader";
71
72    const FIXED_PART_SIZE: usize = PREAMBLE_SIZE + BASIC_SECURITY_HEADER_SIZE;
73}
74
75impl Encode for LicenseHeader {
76    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
77        ensure_fixed_part_size!(in: dst);
78
79        self.security_header.encode(dst)?;
80
81        let flags_with_version = self.preamble_flags.bits() | self.preamble_version.to_u8().unwrap();
82
83        dst.write_u8(self.preamble_message_type.to_u8().unwrap());
84        dst.write_u8(flags_with_version);
85        dst.write_u16(self.preamble_message_size); // msg size
86
87        Ok(())
88    }
89
90    fn name(&self) -> &'static str {
91        Self::NAME
92    }
93
94    fn size(&self) -> usize {
95        Self::FIXED_PART_SIZE
96    }
97}
98
99impl<'de> Decode<'de> for LicenseHeader {
100    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
101        ensure_fixed_part_size!(in: src);
102
103        let security_header = BasicSecurityHeader::decode(src)?;
104
105        if !security_header.flags.contains(BasicSecurityHeaderFlags::LICENSE_PKT) {
106            return Err(invalid_field_err!(
107                "securityHeaderFlags",
108                "invalid security header flags"
109            ));
110        }
111
112        let preamble_message_type = PreambleType::from_u8(src.read_u8())
113            .ok_or_else(|| invalid_field_err!("preambleType", "invalid license type"))?;
114
115        let flags_with_version = src.read_u8();
116        let preamble_message_size = src.read_u16();
117
118        let preamble_flags = PreambleFlags::from_bits(flags_with_version & !PROTOCOL_VERSION_MASK)
119            .ok_or_else(|| invalid_field_err!("preambleFlags", "Got invalid flags field"))?;
120
121        let preamble_version = PreambleVersion::from_u8(flags_with_version & PROTOCOL_VERSION_MASK)
122            .ok_or_else(|| invalid_field_err!("preambleVersion", "Got invalid version in the flags filed"))?;
123
124        Ok(Self {
125            security_header,
126            preamble_message_type,
127            preamble_flags,
128            preamble_version,
129            preamble_message_size,
130        })
131    }
132}
133
134/// [2.2.1.12.1.1] Licensing Preamble (LICENSE_PREAMBLE)
135///
136/// [2.2.1.12.1.1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/73170ca2-5f82-4a2d-9d1b-b439f3d8dadc
137#[repr(u8)]
138#[derive(Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
139pub enum PreambleType {
140    LicenseRequest = 0x01,
141    PlatformChallenge = 0x02,
142    NewLicense = 0x03,
143    UpgradeLicense = 0x04,
144    LicenseInfo = 0x12,
145    NewLicenseRequest = 0x13,
146    PlatformChallengeResponse = 0x15,
147    ErrorAlert = 0xff,
148}
149
150bitflags! {
151    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
152    pub struct PreambleFlags: u8 {
153        const EXTENDED_ERROR_MSG_SUPPORTED = 0x80;
154    }
155}
156
157#[derive(Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
158pub enum PreambleVersion {
159    V2 = 2, // RDP 4.0
160    V3 = 3, // RDP 5.0, 5.1, 5.2, 6.0, 6.1, 7.0, 7.1, 8.0, 8.1, 10.0, 10.1, 10.2, 10.3, 10.4, and 10.5
161}
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub struct BlobType(u16);
165
166impl BlobType {
167    pub const ANY: Self = Self(0x00);
168    pub const DATA: Self = Self(0x01);
169    pub const RANDOM: Self = Self(0x02);
170    pub const CERTIFICATE: Self = Self(0x03);
171    pub const ERROR: Self = Self(0x04);
172    pub const RSA_KEY: Self = Self(0x06);
173    pub const ENCRYPTED_DATA: Self = Self(0x09);
174    pub const RSA_SIGNATURE: Self = Self(0x08);
175    pub const KEY_EXCHANGE_ALGORITHM: Self = Self(0x0d);
176    pub const SCOPE: Self = Self(0x0e);
177    pub const CLIENT_USER_NAME: Self = Self(0x0f);
178    pub const CLIENT_MACHINE_NAME_BLOB: Self = Self(0x10);
179}
180
181#[derive(Debug, Error)]
182pub enum ServerLicenseError {
183    #[error("IO error: {0}")]
184    IOError(#[from] io::Error),
185    #[error("UTF-8 error: {0}")]
186    Utf8Error(#[from] std::string::FromUtf8Error),
187    #[error("invalid preamble field: {0}")]
188    InvalidPreamble(String),
189    #[error("invalid preamble message type field")]
190    InvalidLicenseType,
191    #[error("invalid error code field")]
192    InvalidErrorCode,
193    #[error("invalid state transition field")]
194    InvalidStateTransition,
195    #[error("invalid blob type field")]
196    InvalidBlobType,
197    #[error("unable to generate random number {0}")]
198    RandomNumberGenerationError(String),
199    #[error("unable to retrieve public key from the certificate")]
200    UnableToGetPublicKey,
201    #[error("unable to encrypt RSA public key")]
202    RsaKeyEncryptionError,
203    #[error("invalid License Request key exchange algorithm value")]
204    InvalidKeyExchangeValue,
205    #[error("MAC checksum generated over decrypted data does not match the server's checksum")]
206    InvalidMacData,
207    #[error("invalid platform challenge response data version")]
208    InvalidChallengeResponseDataVersion,
209    #[error("invalid platform challenge response data client type")]
210    InvalidChallengeResponseDataClientType,
211    #[error("invalid platform challenge response data license detail level")]
212    InvalidChallengeResponseDataLicenseDetail,
213    #[error("invalid x509 certificate")]
214    InvalidX509Certificate {
215        source: x509_cert::der::Error,
216        cert_der: Vec<u8>,
217    },
218    #[error("invalid certificate version")]
219    InvalidCertificateVersion,
220    #[error("invalid x509 certificates amount")]
221    InvalidX509CertificatesAmount,
222    #[error("invalid proprietary certificate signature algorithm ID")]
223    InvalidPropCertSignatureAlgorithmId,
224    #[error("invalid proprietary certificate key algorithm ID")]
225    InvalidPropCertKeyAlgorithmId,
226    #[error("invalid RSA public key magic")]
227    InvalidRsaPublicKeyMagic,
228    #[error("invalid RSA public key length")]
229    InvalidRsaPublicKeyLength,
230    #[error("invalid RSA public key data length")]
231    InvalidRsaPublicKeyDataLength,
232    #[error("invalid RSA public key bit length")]
233    InvalidRsaPublicKeyBitLength,
234    #[error("invalid License Header security flags")]
235    InvalidSecurityFlags,
236    #[error("the server returned unexpected error: {0:?}")]
237    UnexpectedError(LicensingErrorMessage),
238    #[error("got unexpected license message")]
239    UnexpectedLicenseMessage,
240    #[error("the server has returned an unexpected error")]
241    UnexpectedServerError(LicensingErrorMessage),
242    #[error("the server has returned STATUS_VALID_CLIENT (not an error)")]
243    ValidClientStatus(LicensingErrorMessage),
244    #[error("invalid Key Exchange List field")]
245    InvalidKeyExchangeAlgorithm,
246    #[error("received invalid company name length (Product Information): {0}")]
247    InvalidCompanyNameLength(u32),
248    #[error("received invalid product ID length (Product Information): {0}")]
249    InvalidProductIdLength(u32),
250    #[error("received invalid scope count field: {0}")]
251    InvalidScopeCount(u32),
252    #[error("received invalid certificate length: {0}")]
253    InvalidCertificateLength(u32),
254    #[error("blob too small")]
255    BlobTooSmall,
256    #[error("PDU error: {0}")]
257    Pdu(PduError),
258}
259
260impl From<PduError> for ServerLicenseError {
261    fn from(e: PduError) -> Self {
262        Self::Pdu(e)
263    }
264}
265
266impl From<LicensingErrorMessage> for ServerLicenseError {
267    fn from(e: LicensingErrorMessage) -> Self {
268        Self::UnexpectedError(e)
269    }
270}
271
272#[derive(Debug, PartialEq)]
273pub struct BlobHeader {
274    pub blob_type: BlobType,
275    pub length: usize,
276}
277
278impl BlobHeader {
279    const NAME: &'static str = "BlobHeader";
280
281    const FIXED_PART_SIZE: usize = 2 /* blobType */ + 2 /* len */;
282
283    pub fn new(blob_type: BlobType, length: usize) -> Self {
284        Self { blob_type, length }
285    }
286}
287
288impl Encode for BlobHeader {
289    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
290        ensure_fixed_part_size!(in: dst);
291
292        dst.write_u16(self.blob_type.0);
293        dst.write_u16(cast_length!("len", self.length)?);
294
295        Ok(())
296    }
297
298    fn name(&self) -> &'static str {
299        Self::NAME
300    }
301
302    fn size(&self) -> usize {
303        Self::FIXED_PART_SIZE
304    }
305}
306
307impl<'de> Decode<'de> for BlobHeader {
308    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
309        ensure_fixed_part_size!(in: src);
310
311        let blob_type = BlobType(src.read_u16());
312        let length = cast_length!("len", src.read_u16())?;
313
314        Ok(Self { blob_type, length })
315    }
316}
317
318fn compute_mac_data(mac_salt_key: &[u8], data: &[u8]) -> Vec<u8> {
319    let data_len_buffer = (data.len() as u32).to_le_bytes();
320
321    let pad_one: [u8; 40] = [0x36; 40];
322
323    let mut hasher = sha1::Sha1::new();
324    hasher.update(
325        [mac_salt_key, pad_one.as_ref(), data_len_buffer.as_ref(), data]
326            .concat()
327            .as_slice(),
328    );
329    let sha_result = hasher.finalize();
330
331    let pad_two: [u8; 48] = [0x5c; 48];
332
333    let mut md5 = md5::Md5::new();
334    md5.update(
335        [mac_salt_key, pad_two.as_ref(), sha_result.as_ref()]
336            .concat()
337            .as_slice(),
338    );
339
340    md5.finalize().to_vec()
341}
342
343#[derive(Debug, PartialEq)]
344pub enum LicensePdu {
345    ClientNewLicenseRequest(ClientNewLicenseRequest),
346    ClientLicenseInfo(ClientLicenseInfo),
347    ClientPlatformChallengeResponse(ClientPlatformChallengeResponse),
348    ServerLicenseRequest(ServerLicenseRequest),
349    ServerPlatformChallenge(ServerPlatformChallenge),
350    ServerUpgradeLicense(ServerUpgradeLicense),
351    LicensingErrorMessage(LicensingErrorMessage),
352}
353
354impl<'de> Decode<'de> for LicensePdu {
355    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
356        let license_header = LicenseHeader::decode(src)?;
357
358        match license_header.preamble_message_type {
359            PreambleType::LicenseRequest => Ok(ServerLicenseRequest::decode(license_header, src)?.into()),
360            PreambleType::PlatformChallenge => Ok(ServerPlatformChallenge::decode(license_header, src)?.into()),
361            PreambleType::NewLicense | PreambleType::UpgradeLicense => {
362                Ok(ServerUpgradeLicense::decode(license_header, src)?.into())
363            }
364            PreambleType::LicenseInfo => Err(unsupported_value_err!(
365                "LicensePdu::LicenseInfo",
366                "LicenseInfo is not supported".to_owned()
367            )),
368            PreambleType::NewLicenseRequest => Ok(ClientNewLicenseRequest::decode(license_header, src)?.into()),
369            PreambleType::PlatformChallengeResponse => {
370                Ok(ClientPlatformChallengeResponse::decode(license_header, src)?.into())
371            }
372            PreambleType::ErrorAlert => Ok(LicensingErrorMessage::decode(license_header, src)?.into()),
373        }
374    }
375}
376
377impl Encode for LicensePdu {
378    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
379        match self {
380            Self::ClientNewLicenseRequest(ref pdu) => pdu.encode(dst),
381            Self::ClientLicenseInfo(ref pdu) => pdu.encode(dst),
382            Self::ClientPlatformChallengeResponse(ref pdu) => pdu.encode(dst),
383            Self::ServerLicenseRequest(ref pdu) => pdu.encode(dst),
384            Self::ServerPlatformChallenge(ref pdu) => pdu.encode(dst),
385            Self::ServerUpgradeLicense(ref pdu) => pdu.encode(dst),
386            Self::LicensingErrorMessage(ref pdu) => pdu.encode(dst),
387        }
388    }
389
390    fn name(&self) -> &'static str {
391        match self {
392            Self::ClientNewLicenseRequest(pdu) => pdu.name(),
393            Self::ClientLicenseInfo(pdu) => pdu.name(),
394            Self::ClientPlatformChallengeResponse(pdu) => pdu.name(),
395            Self::ServerLicenseRequest(pdu) => pdu.name(),
396            Self::ServerPlatformChallenge(pdu) => pdu.name(),
397            Self::ServerUpgradeLicense(pdu) => pdu.name(),
398            Self::LicensingErrorMessage(pdu) => pdu.name(),
399        }
400    }
401
402    fn size(&self) -> usize {
403        match self {
404            Self::ClientNewLicenseRequest(pdu) => pdu.size(),
405            Self::ClientLicenseInfo(pdu) => pdu.size(),
406            Self::ClientPlatformChallengeResponse(pdu) => pdu.size(),
407            Self::ServerLicenseRequest(pdu) => pdu.size(),
408            Self::ServerPlatformChallenge(pdu) => pdu.size(),
409            Self::ServerUpgradeLicense(pdu) => pdu.size(),
410            Self::LicensingErrorMessage(pdu) => pdu.size(),
411        }
412    }
413}
414
415impl From<ClientNewLicenseRequest> for LicensePdu {
416    fn from(pdu: ClientNewLicenseRequest) -> Self {
417        Self::ClientNewLicenseRequest(pdu)
418    }
419}
420
421impl From<ClientLicenseInfo> for LicensePdu {
422    fn from(pdu: ClientLicenseInfo) -> Self {
423        Self::ClientLicenseInfo(pdu)
424    }
425}
426
427impl From<ClientPlatformChallengeResponse> for LicensePdu {
428    fn from(pdu: ClientPlatformChallengeResponse) -> Self {
429        Self::ClientPlatformChallengeResponse(pdu)
430    }
431}
432
433impl From<ServerLicenseRequest> for LicensePdu {
434    fn from(pdu: ServerLicenseRequest) -> Self {
435        Self::ServerLicenseRequest(pdu)
436    }
437}
438
439impl From<ServerPlatformChallenge> for LicensePdu {
440    fn from(pdu: ServerPlatformChallenge) -> Self {
441        Self::ServerPlatformChallenge(pdu)
442    }
443}
444
445impl From<ServerUpgradeLicense> for LicensePdu {
446    fn from(pdu: ServerUpgradeLicense) -> Self {
447        Self::ServerUpgradeLicense(pdu)
448    }
449}
450
451impl From<LicensingErrorMessage> for LicensePdu {
452    fn from(pdu: LicensingErrorMessage) -> Self {
453        Self::LicensingErrorMessage(pdu)
454    }
455}