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); 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#[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, V3 = 3, }
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 + 2 ;
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}